X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FMPEG.cpp;h=9bd2acee7e42980f68dd6b02d51277fea97aa5ec;hb=6159b54a6ea46408a71c74b7c0a999c9ff5449e5;hp=0f60a8f2cee9f365fc6bc2a00805b29c830b29f9;hpb=8095eaa320551b6795d0368c0ad0c227a3167caa;p=asdcplib.git diff --git a/src/MPEG.cpp b/src/MPEG.cpp index 0f60a8f..9bd2ace 100755 --- a/src/MPEG.cpp +++ b/src/MPEG.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005, John Hurst +Copyright (c) 2005-2006, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,6 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include +using Kumu::DefaultLogSink; // walk a buffer stopping at the end of the buffer or the end of a VES // start code '00 00 01'. If successful, returns address of first byte @@ -103,9 +105,9 @@ public: h__StreamState() : m_State(ST_IDLE) {} ~h__StreamState() {} - void Goto_START_HEADER() { m_State = ST_START_HEADER; } - void Goto_IN_HEADER() { m_State = ST_IN_HEADER; } - void Goto_IDLE() { m_State = ST_IDLE; } + void Goto_START_HEADER() { m_State = ST_START_HEADER; } + void Goto_IN_HEADER() { m_State = ST_IN_HEADER; } + void Goto_IDLE() { m_State = ST_IDLE; } bool Test_IDLE() { return m_State == ST_IDLE; } bool Test_START_HEADER() { return m_State == ST_START_HEADER; } bool Test_IN_HEADER() { return m_State == ST_IN_HEADER; } @@ -115,7 +117,7 @@ public: ASDCP::MPEG2::VESParser::VESParser() : - m_Delegate(0), m_HBufLen(0), m_ZeroCount(0), m_Partial(false) + m_Delegate(0), m_HBufLen(0), m_ZeroCount(0) { m_State = new h__StreamState; } @@ -139,7 +141,6 @@ ASDCP::MPEG2::VESParser::Reset() m_State->Goto_IDLE(); m_HBufLen = 0; m_ZeroCount = 0; - m_Partial = false; } // @@ -149,17 +150,18 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len) ASDCP_TEST_NULL(buf); ASDCP_TEST_NULL(m_Delegate); - Result_t result; - const byte_t* end_p = buf + buf_len; - const byte_t* run_pos = buf; // track runs of uninteresting data as a position and count - ui32_t run_len = 0; + Result_t result = RESULT_OK; + register const byte_t* end_p = buf + buf_len; + register const byte_t* run_pos = buf; // track runs of uninteresting data using a position and count + register ui32_t run_len = 0; // search for MPEG2 headers // copy interesting data to a buffer and pass to delegate for processing - for ( const byte_t* p = buf; p < end_p; p++ ) + for ( register const byte_t* p = buf; p < end_p; p++ ) { if ( m_State->Test_IN_HEADER() ) { + assert(run_len==0); m_HBuf[m_HBufLen++] = *p; assert(m_HBufLen < VESHeaderBufSize); } @@ -170,8 +172,44 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len) if ( m_State->Test_START_HEADER() ) // *p is a start code { - // Do we already have a header? We need to flush it... - if ( m_HBufLen > 0) + if ( m_HBufLen == 0) // not already collecting a header + { + m_HBuf[0] = m_HBuf[1] = 0; m_HBuf[2] = 1; m_HBuf[3] = *p; + + // is this one we want? + if ( *p == PIC_START || *p == SEQ_START || *p == EXT_START || *p == GOP_START ) + { + m_HBufLen = 4; + m_State->Goto_IN_HEADER(); + + switch ( run_len ) + { + case 1: // we suppressed writing 001 when exiting from the last call + case 4: // we have exactly 001x + break; + case 2: // we have 1x + case 3: // we have 01x + m_Delegate->Data(this, run_pos, (run_len == 2 ? -2 : -1)); + break; + + default: + m_Delegate->Data(this, run_pos, run_len - 4); + } + + run_len = 0; + } + else + { + m_State->Goto_IDLE(); + + if ( run_len == 1 ) // did we suppress writing 001 when exiting from the last call? + { + m_Delegate->Data(this, m_HBuf, 4); + run_len = 0; + } + } + } + else // currently collecting a header, requires a flush before handling { m_HBufLen -= 3; // remove the current partial start code @@ -184,53 +222,43 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len) case GOP_START: result = m_Delegate->GOP(this, m_HBuf, m_HBufLen); break; default: - DefaultLogSink().Error("Unexpected start code: %02x at byte %lu\n", + DefaultLogSink().Error("Unexpected start code: %02x at byte %u\n", m_HBuf[3], (ui32_t)(p - buf)); result = RESULT_RAW_FORMAT; } - // the next run starts with the start code that got us here - run_len = 4; - run_pos = p-3; - m_HBufLen = 0; - // Parser handlers return RESULT_FALSE to teriminate without error if ( result != RESULT_OK ) { m_State->Goto_IDLE(); return result; } - } - - // all headers start with this same start code: 00 00 01 xx - m_HBuf[0] = m_HBuf[1] = 0; m_HBuf[2] = 1; m_HBuf[3] = *p; + + m_HBuf[0] = m_HBuf[1] = 0; m_HBuf[2] = 1; m_HBuf[3] = *p; // 001x + run_len = 0; - // is this a header we want? - if ( *p == PIC_START || *p == SEQ_START || *p == EXT_START || *p == GOP_START ) - { - // we're starting a new header, flush the current run - if ( run_len > 4 ) + // is this a header we want? + if ( *p == PIC_START || *p == SEQ_START || *p == EXT_START || *p == GOP_START ) { - m_Delegate->Data(this, run_pos, run_len - 4); - run_len = 0; + m_HBufLen = 4; + m_State->Goto_IN_HEADER(); } + else + { + m_HBufLen = 0; + m_State->Goto_IDLE(); - m_Partial = false; - m_HBufLen = 4; - m_State->Goto_IN_HEADER(); - } - else - { - if ( *p == FIRST_SLICE ) - result = m_Delegate->Slice(this); + if ( *p >= FIRST_SLICE && *p <= LAST_SLICE ) + { + result = m_Delegate->Slice(this, *p); - if ( m_Partial ) - { - m_Partial = false; - m_Delegate->Data(this, m_HBuf, 3); + if ( result != RESULT_OK ) + return result; + } + + m_Delegate->Data(this, m_HBuf, 4); + run_pos = p+1; } - - m_State->Goto_IDLE(); } } else if ( *p == 0 ) @@ -248,9 +276,9 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len) if ( run_len > 0 ) { - if ( m_State->Test_START_HEADER() ) + if ( m_State->Test_START_HEADER() && run_len != 0 ) { - m_Partial = true; // 'partial' means we have a partial header in progress + assert(run_len > 2); run_len -= 3; }