📄 parse656data.cpp
字号:
/*+++ *******************************************************************\
*
* Copyright and Disclaimer:
*
* ---------------------------------------------------------------
* This software is provided "AS IS" without warranty of any kind,
* either expressed or implied, including but not limited to the
* implied warranties of noninfringement, merchantability and/or
* fitness for a particular purpose.
* ---------------------------------------------------------------
*
* Copyright (c) 2008 Conexant Systems, Inc.
* All rights reserved.
*
\******************************************************************* ---*/
#include "Parse656Data.h"
#include "BasePin.h"
#define SAV_ACTIVE_VIDEO_FIELD1 0x80
#define EAV_ACTIVE_VIDEO_FIELD1 0x90
#define SAV_ACTIVE_VIDEO_FIELD2 0xC0
#define EAV_ACTIVE_VIDEO_FIELD2 0xD0
#define SAV_VBLANK_FIELD1 0xA0
#define EAV_VBLANK_FIELD1 0xB0
#define SAV_VBLANK_FIELD2 0xE0
#define EAV_VBLANK_FIELD2 0xF0
#define SAV_VBI_FIELD1 0x20
#define EAV_VBI_FIELD1 0x30
#define SAV_VBI_FIELD2 0x60
#define EAV_VBI_FIELD2 0x70
//This is not a real SAV, but a value used to save the state when we had a partial ancillary
// buffer at a buffer boundary
#define SAV_PARTIAL_ANCILLARY 0xA5
//Ancillary packet data ID's
#define ANCILLARY_DID_AUDIO 0xBF
#define ANCILLARY_DID_VBI_FIELD1 0x91
#define ANCILLARY_DID_VBI_FIELD2 0x55
/////////////////////////////////////////////////////////////////////////////////////////
Parse656Data:: Parse656Data():
_is_partial_line(FALSE),
_last_sav(0),
_last_video_sav(0),
_video_parse_buffer(1440, 240),
_vbi_parse_buffer(1440, 12),
_field_num(0)
{
for(DWORD i = 0; i < 4; i++)
{
_end_of_buffer_bytes[i] = 0;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID Parse656Data::setPin(BasePin* p_pin)
{
PIN_TYPES pin_type = p_pin->getPinType();
switch(pin_type)
{
case PIN_TYPE_VIDEO:
_video_parse_buffer.setPin(p_pin);
break;
case PIN_TYPE_VBI:
_vbi_parse_buffer.setPin(p_pin);
break;
case PIN_TYPE_AUDIO: //for HANC Audio use
_audio_parse_buffer.setPin(p_pin);
break;
case PIN_TYPE_SLICED_CC:
_sliced_cc_buffer.setPin(p_pin);
break;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID Parse656Data::releasePin(BasePin* p_pin)
{
PIN_TYPES pin_type = p_pin->getPinType();
switch(pin_type)
{
case PIN_TYPE_VIDEO:
_video_parse_buffer.releasePin();
break;
case PIN_TYPE_VBI:
_vbi_parse_buffer.releasePin();
break;
case PIN_TYPE_AUDIO: // for HANC Audio use
_audio_parse_buffer.releasePin();
break;
case PIN_TYPE_SLICED_CC:
_sliced_cc_buffer.releasePin(); //different class
break;
}
}
VOID Parse656Data::notifyPinFormatChange(BasePin* p_pin)
{
PIN_TYPES pin_type = p_pin->getPinType();
switch(pin_type)
{
case PIN_TYPE_VIDEO:
_video_parse_buffer.notifyPinFormatChange();
break;
case PIN_TYPE_VBI:
_vbi_parse_buffer.notifyPinFormatChange();
break;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
DWORD Parse656Data::getLine(BYTE sav_eav, PBYTE p_buffer, DWORD buffer_size)
{
DWORD bytes_copied = 0;
ParseBuffer* p_parse_buffer = NULL;
FIELD_TYPE current_field = FIELD_INVALID;
switch(sav_eav)
{
case SAV_ACTIVE_VIDEO_FIELD1:
// looking for skipped line which occurred in PAL 720x480 mode. In this case,
// there will be no active data contained between the SAV and EAV
if ( (buffer_size > 3) &&
(p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
(p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2)
)
)
{
return bytes_copied;
}
p_parse_buffer = &_video_parse_buffer;
current_field = FIELD_1;
break;
case SAV_ACTIVE_VIDEO_FIELD2:
// looking for skipped line which occurred in PAL 720x480 mode. In this case,
// there will be no active data contained between the SAV and EAV
if ( (buffer_size > 3) &&
(p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
(p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2)
)
)
{
return bytes_copied;
}
p_parse_buffer = &_video_parse_buffer;
current_field = FIELD_2;
break;
case SAV_VBI_FIELD1:
p_parse_buffer = &_vbi_parse_buffer;
current_field = FIELD_1;
break;
case SAV_VBI_FIELD2:
p_parse_buffer = &_vbi_parse_buffer;
current_field = FIELD_2;
break;
//Special case to specify that we were part way through an ancillary packet at
// a buffer break. Since audio buffers are small, there should be no
// way for one to span more than two buffers.
case SAV_PARTIAL_ANCILLARY:
bytes_copied = _ancillary_packet.submitData(p_buffer, buffer_size);
//Handle the case where the packet was not valid.
if(bytes_copied == 0)
{
//Invalid ancillary packet
_ancillary_packet.clearData();
break;
}
p_buffer += bytes_copied;
buffer_size -= bytes_copied;
if(_ancillary_packet.isPacketComplete())
{
//complete the packet
completeAncillaryPacket();
_is_partial_line = FALSE;
}
else
{
//It is unlikely we will ever need to cross two buffer boundaries
//But break if we do.
break;
}
//FALL THROUGH to test for another ancillary packet immediately following
//Search for ancillary packets. Audio is stored in ancillary data packets, which
//are found immediately after an EAV code. The packet will always start with
//the pattern 0x00 0xFF 0xFF. The packets are of variable length, but will
//be a maximum of 16 data bytes and 6 header bytes.
case EAV_ACTIVE_VIDEO_FIELD1:
case EAV_ACTIVE_VIDEO_FIELD2:
case EAV_VBI_FIELD1:
case EAV_VBI_FIELD2:
case EAV_VBLANK_FIELD1:
case EAV_VBLANK_FIELD2:
{
DWORD total_bytes_copied = bytes_copied;
while(buffer_size > 0)
{
//Although ancillary packets should follow one another without gaps,
//there is apparantly a bug where Mako is duplicating the last byte
// of the sliced CC packets, causing there to be one more byte in the
// packet than expected. This can cause us to lose the packet following
// it because the packet header will be off one byte from what we expect.
// To work around it, if the next byte is not 00, check the one after it.
if(*p_buffer != 0x00)
{
//If the second byte is 00 and the first byte was not 0xFF
// (which would be the case for an FF 00 00 SAV/EAV code)
// then advance the buffer pointer by one and try to find an ancillary
// packet.
if((buffer_size >= 2) &&
(p_buffer[0] != 0xFF) &&
(p_buffer[1] == 0x00))
{
p_buffer++;
buffer_size--;
total_bytes_copied++;
}
else
{
break;
}
}
//Parse the ancillary packet
bytes_copied = _ancillary_packet.submitData(p_buffer, buffer_size);
//Handle the case where the packet is not valid.
if(bytes_copied == 0)
{
//Invalid ancillary packet
_ancillary_packet.clearData();
break;
}
if(_ancillary_packet.isPacketComplete())
{
//complete the packet
completeAncillaryPacket();
_is_partial_line = FALSE;
p_buffer += bytes_copied;
buffer_size -= bytes_copied;
total_bytes_copied += bytes_copied;
}
else
{
//The packet must be overlapping a buffer boundary. Mark that it
// is a partial line and return.
_is_partial_line = TRUE;
_last_sav = SAV_PARTIAL_ANCILLARY;
total_bytes_copied += bytes_copied;
return total_bytes_copied;
}
}
return total_bytes_copied;
}
}
_is_partial_line = FALSE;
if(p_parse_buffer)
{
_last_sav = sav_eav;
bytes_copied = p_parse_buffer->copyLine(p_buffer, buffer_size, current_field, &_is_partial_line);
}
return bytes_copied;
}
/////////////////////////////////////////////////////////////////////////////////////////
//This function is called when we have a complete ancillary packet. Pass it to the
// approptiate parse buffer to complete a buffer.
//
VOID Parse656Data::completeAncillaryPacket()
{
BYTE data_id = _ancillary_packet.getDataID();
switch(data_id)
{
case ANCILLARY_DID_AUDIO:
_audio_parse_buffer.parseBuffer(&_ancillary_packet);
break;
case ANCILLARY_DID_VBI_FIELD1:
_sliced_cc_buffer.parseBuffer(&_ancillary_packet);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -