⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psi_task.c

📁 pnx1500 mpeg2 ts stream demo
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -