📄 psi_task.c
字号:
/*
* Copyright (c) 2004, 2005 Koninklijke Philips Electronics N V. Includes code
* copyright (c) 2004 by VCom Electronics Inc; copyright transferred by verbal
* agreement between Tim Meakin and Jonathan Coxhead, November 2004. All rights
* reserved.
*
* This source code and any compilation or derivative thereof is the proprietary
* information of Koninklijke Philips Electronics N V and is confidential in
* nature. Under no circumstances is this software to be exposed to or placed
* under an Open Source License of any type without the express written
* permission of Koninklijke Philips Electronics N V.
*
* #############################################################################
*
* Module: %name: psi_task.c % %version: 1 %
*
* %date_created: Fri Mar 11 11:55:13 2005 % %created_by: jcoxhead %
*
* %date_modified: Fri Jun 14 11:31:56 2002 %
*
* #############################################################################
*/
/* --------------------------------------------------------------------------
*
* DESCRIPTION: Task to handle PSI data extracted by Transport Stream
* Demux.
*
* --------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <psos.h>
#include <tmosal.h>
#include <tmMainStreaming.h>
#include <tmDbg.h>
#include <queue.h>
#include "tmalDemuxMpegTS.h"
#include "tmolDemuxMpegTS.h"
#include "psi_task.h"
//---------------------------------------------------------------------------
// Global data
//---------------------------------------------------------------------------
typedef struct programInfo
{
UInt16 program_number;
UInt16 program_map_PID;
TAILQ_ENTRY( programInfo ) PATentries;
} programNumInfo_s;
// Maximum size of a PAT section is 1021 bytes.
// This structure's variables are named with this convention because
// it is the exact way they are named in the MPEG-2 standard
// any extra variables added to the structure are named without underscores
typedef struct
{
UInt8 table_ID;
UInt8 section_syntax_indicator;
UInt16 section_length;
UInt16 transport_stream_id;
UInt8 version_number;
UInt8 current_next_indicator;
UInt8 section_number;
UInt8 last_section_number;
programNumInfo_s *programInfo;
programNumInfo_s *nextProgramInfo;
UInt32 CRC_32;
} PATInfo_s;
// Maximum size of a PMT section is 1021 bytes
typedef struct PMTpids
{
UInt8 stream_type;
UInt16 elementary_PID;
UInt16 ES_info_length;
TAILQ_ENTRY( PMTpids ) PMTentries;
} streamTypeInfo_s;
// Maximum size of a PAT section is 1021 bytes.
// This structure's variables are named with this convention because
// it is the exact way they are named in the MPEG-2 standard
// any extra variables added to the structure are named without underscores
typedef struct
{
UInt8 table_ID;
UInt8 section_syntax_indicator;
UInt16 section_length;
UInt16 program_number;
UInt8 version_number;
UInt8 current_next_indicator;
UInt8 section_number;
UInt8 last_section_number;
UInt16 PCR_PID;
UInt16 program_info_length;
streamTypeInfo_s *PMTpids;
streamTypeInfo_s *nextPMTpids;
UInt32 CRC_32;
UInt16 PMTPid;
UInt16 numOfPids;
} PMTInfo_s;
static UInt8 patBuffer[188];
static Bool gDoNotPrint[100];
static Int gPmtCounter;
static PATInfo_s gPATInfo;
static PMTInfo_s gPMTInfo;
static tmosalSemHandle_t gPsiSemaphore;
static Int gDemuxInst = 0;
static Bool bSearchForProgram = False;
static Bool bChangePids = True;
static pids_t gPids;
//---------------------------------------------------------------------------
// Function prototypes
//---------------------------------------------------------------------------
static tmErrorCode_t psiParsePat( ptaskArgs_t taskArgs,
UInt8 *section,
UInt32 length );
static Bool psiParsePmt( UInt32 pid,
UInt8 *section,
UInt32 sectionLength,
void *userData,
UInt32 *userOutData );
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
TAILQ_HEAD( , programInfo ) programList;
TAILQ_HEAD( , PMTpids ) pidList;
//---------------------------------------------------------------------------
void
psiDataTask(
pVoid pArgs )
{
UInt32 taskID = 0;
ptmAvPacket_t packetPtr = Null;
ptaskArgs_t psiTaskArgsPtr = (ptaskArgs_t)pArgs;
taskArgs_t psiTaskArgs;
static Bool bPatAdded = False;
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_ENTER, "psiDataTask") )
// Make local copy of parameters passed in on the stack
psiTaskArgs.instance = psiTaskArgsPtr->instance;
psiTaskArgs.fullQ = psiTaskArgsPtr->fullQ;
psiTaskArgs.emptyQ = psiTaskArgsPtr->emptyQ;
gDemuxInst = psiTaskArgs.instance;
// Obtain the task identifier
t_ident( (char *)0, 0, &taskID );
DBG_ISR_PRINT( (dbgTsDemux, DBG_LEVEL_1, "psiDataTask ID=0x%x", taskID) )
EQ_ERRCHK( psiTaskArgs.instance, 0 )
if ( bPatAdded == False )
{
// Request PID 0, the PAT
ERRCHK( tmolDemuxMpegTsAddRedirectedPid(
psiTaskArgs.instance,
0, // PAT
DEMUXMPEGTS_PSI_OUTPUT,
demuxMpegTSSectionCRC,
0, // Not interested in the clock
Null,
Null ) )
bPatAdded = True;
}
// Loop forever
for ( ;; )
{
// Wait to receive a full packet from an input connection queue
ERRCHK( qDataInGetFull( psiTaskArgs.fullQ, False, &packetPtr ) )
// Check if we have been ordered to kill ourself
if ( bKillPsiDataTask == True )
{
DBG_ISR_PRINT( (dbgTsDemux, DBG_LEVEL_1,
"psiDataTask: Received kill signal, exiting") )
tmosalTaskExit();
}
// Do something
if ( packetPtr->header->userSender == 0 )
{
psiParsePat( &psiTaskArgs, packetPtr->buffers[0].data,
packetPtr->buffers[0].dataSize );
}
// Return an empty packet to an input connection queue
ERRCHK( qDataInPutEmpty( psiTaskArgs.emptyQ, packetPtr ) )
} // End loop
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
tmErrorCode_t
psiGetPids(
pids_t *pid )
{
tmErrorCode_t rval = TM_OK;
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_ENTER, "psiGetPids") )
gPids.pcrPid = DEMUXMPEGTS_NO_PID;
gPids.videoPid = DEMUXMPEGTS_NO_PID;
gPids.mainAudioPid = DEMUXMPEGTS_NO_PID;
gPids.secondaryAudioPid = DEMUXMPEGTS_NO_PID;
ERRCHK( tmosalSemAcquire( gPsiSemaphore, Null ) )
// Set the values of the PIDs we are returning
pid->pcrPid = gPids.pcrPid;
pid->videoPid = gPids.videoPid;
pid->mainAudioPid = gPids.mainAudioPid;
pid->secondaryAudioPid = gPids.secondaryAudioPid;
if ( (gPids.pcrPid == DEMUXMPEGTS_NO_PID) &&
(gPids.videoPid == DEMUXMPEGTS_NO_PID) &&
(gPids.mainAudioPid == DEMUXMPEGTS_NO_PID) &&
(gPids.secondaryAudioPid == DEMUXMPEGTS_NO_PID) )
{
rval = TM_ERR_BAD_INDEX;
}
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_LEAVE, "psiGetPids") )
return( rval );
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
tmErrorCode_t
psiGetProgramNo(
Int *num )
{
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_ENTER, "psiGetProgramNo") )
// Set the value of the Program Number we are returning
*num = gPids.programNum;
gPids.programNum = 0;
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_LEAVE, "psiGetProgramNo") )
return( TM_OK );
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
tmErrorCode_t
psiInit(
void )
{
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_ENTER, "psiInit") )
gPids.pcrPid = DEMUXMPEGTS_NO_PID;
gPids.videoPid = DEMUXMPEGTS_NO_PID;
gPids.mainAudioPid = DEMUXMPEGTS_NO_PID;
gPids.secondaryAudioPid = DEMUXMPEGTS_NO_PID;
gPids.programNum = 0;
ERRCHK( tmosalSemCreate( 0, &gPsiSemaphore, tmosalSemCreateFlagNone ) )
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_LEAVE, "psiInit") )
return( TM_OK );
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
static tmErrorCode_t
psiParsePat(
ptaskArgs_t taskArgs,
UInt8 *section,
UInt32 length )
{
Int i = 0;
Int j = 0;
Bool bProgramFound = False;
Bool bChanged = False;
pids_t dummyVar;
static Int prevProgramNum = 0;
DBG_ISR_PRINT( (dbgTsDemux, DBG_INTERNAL_ENTER, "psiParsePat") )
TAILQ_INIT( &programList );
for ( i = 0; i < length; i++ )
{
if ( (patBuffer[i] ^ section[i]) != 0 )
{
bChanged = True;
patBuffer[i] = section[i];
}
}
if ( bChanged == True )
{
*patBuffer = *section;
gPATInfo.table_ID = section[0];
gPATInfo.section_syntax_indicator = (section[1] >> 7) & 0x01;
gPATInfo.section_length = ((section[1] & 0x0F) << 4) | section[2];
gPATInfo.transport_stream_id = (section[3] << 8) | section[4];
gPATInfo.version_number = (section[5] >> 1) & 0x3F;
gPATInfo.current_next_indicator = section[5] & 0x01;
gPATInfo.section_number = section[6];
gPATInfo.last_section_number = section[7];
i = length - 1;
gPATInfo.CRC_32 = (UInt8)(section[i] << 24) +
(UInt8)(section[i+1] << 16) +
(UInt8)(section[i+2] << 8) +
(UInt8)(section[i+3]);
}
// If there is a new program number to check, parse the PMT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -