summaryrefslogtreecommitdiff
path: root/command/pes2es.cpp
blob: 4c74e5f92c938ef29bdd70b7ea168c5d5effcd8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * pes2es.cpp: A program for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 */

#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#include "pes2es.h"
#include <stdio.h>
cMarkAdPES2ES::cMarkAdPES2ES(const char *QueueName, int QueueSize)
{
    queue = new cMarkAdPaketQueue(QueueName,QueueSize);
    type=0;
}

cMarkAdPES2ES::~cMarkAdPES2ES()
{
    if (queue) delete queue;
}

void cMarkAdPES2ES::Clear()
{
    if (queue) queue->Clear();
}

void cMarkAdPES2ES::Process(MarkAdPid Pid, uchar *PESData, int PESSize, MarkAdPacket *ESPkt)
{
    if (!ESPkt) return;

    if (PESData)
    {
        struct PESHDR *peshdr=(struct PESHDR *) PESData;

        // first check some simple things
        if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1))
        {
            Clear();
            return;
        }

        if (peshdr->StreamID<=0xBC) return;

        int Length=(peshdr->LenH<<8)+peshdr->LenL;
        if (Length) Length+=sizeof(PESHDR);
        if (Length!=PESSize)
        {
            if ((peshdr->StreamID & 0xF0)==0xE0) return;
            Clear();
            return;
        }

        switch (Pid.Type)
        {
        case MARKAD_PIDTYPE_VIDEO_H262:
            if ((peshdr->StreamID & 0xF0)!=0xE0) return;
            type=MA_PACKET_PKT;
            break;
        case MARKAD_PIDTYPE_VIDEO_H264:
            if ((peshdr->StreamID & 0xF0)!=0xE0) return;
            type=MA_PACKET_H264;
            break;
        case MARKAD_PIDTYPE_AUDIO_AC3:
            if (peshdr->StreamID!=0xBD) return;
            type=MA_PACKET_AC3;
            break;
        case MARKAD_PIDTYPE_AUDIO_MP2:
            if ((peshdr->StreamID<0xC0) || (peshdr->StreamID>0xDF)) return;
            type=MA_PACKET_MP2;
            break;
        default:
            Clear();
            return;
        }

        struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];

        uchar *buf;
        int buflen;

        if (peshdropt->MarkerBits==0x2)
        {
            // we have an optional PES header
            int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
                     peshdropt->Length;
            buf=&PESData[bpos];
            buflen=PESSize-bpos;
            if (peshdropt->PTSDTS>1)
            {
                struct PESHDROPTPTS *peshdroptpts=(struct PESHDROPTPTS *) &PESData[sizeof(struct PESHDR)+
                                                              sizeof(struct PESHDROPT)];

                if (peshdroptpts->Marker1 && peshdroptpts->Marker2 && peshdroptpts->Marker3)
        {
                    unsigned int pts=0;
                    pts|=((peshdroptpts->PTS29_15_H<<7|peshdroptpts->PTS29_15_L)<<15);
                    pts|=(peshdroptpts->PTS14_0_H<<7|peshdroptpts->PTS14_0_L);
                    pts|=(peshdroptpts->PTS32_30<<30);
                    ESPkt->Timestamp=pts;
                }
            }
        }
        else
        {
            int bpos=sizeof(struct PESHDR);
            buf=&PESData[bpos];
            buflen=PESSize-bpos;
        }
        queue->Put(buf,buflen);
    }
    if (type) ESPkt->Data=queue->GetPacket(&ESPkt->Length,type);
    return;
}