Generate PCR from PTS
Asked Answered
S

3

7

I am trying to create PCR from PTS as follows.

        S64 nPcr = nPts * 9 / 100;  
        pTsBuf[4] = 7 + nStuffyingBytes;  
        pTsBuf[5] = 0x10;   /* flags */  
        pTsBuf[6] = ( nPcr >> 25 )&0xff;  
        pTsBuf[7] = ( nPcr >> 17 )&0xff;  
        pTsBuf[8] = ( nPcr >> 9  )&0xff;  
        pTsBuf[9] = ( nPcr >> 1  )&0xff;  
        pTsBuf[10]= ( nPcr << 7  )&0x80;  
        pTsBuf[11]= 0; 

But the problem is VLC is playing only first frame and not playing any other frames. and I am getting the warning "early picture skipped".

Could any one help me in converting from PTS to PCR..

Sexivalent answered 1/6, 2011 at 10:48 Comment(0)
O
16

First, the PCR has 33+9 bits, the PTS 33 bits. The 33 bit-portion (called PCR_base) runs at 90kHz, as does the PTS. The remaining 9 bits are called PCR_ext and run at 27MHz.

Thus, this is how you could calculate the PCR:

S64 nPcr = (S64)nPts << 9;

Note that there should be a time-offset between the PTSs of the multiplexed streams and the PCR, it's usually in the range of a few hundred ms, depending on the stream.

The respective decoder needs some time to decode the data and get it ready for presentation at the time given by the respective PTS, that's why the PTSs are always "ahead" of the PCR. ISO-13818 and some DVB specs give specifics about buffering and (de)multiplexing.

About your bitshifting I'm not sure, this is a code snippet of mine. The comment may help in shifting the bits to the right place, R stands for reserved.

data[4] = 7;
data[5] = 1 << 4;   // PCR_flag

// pcr has 33+9=42 bits

//        4           3          2          1          0
// 76543210 98765432 10987654 32109876 54321098 76543210
// xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xRRRRRRx xxxxxxxx
// 10987654 32109876 54321098 76543210 9      8 76543210
//  4          3          2          1                 0
// b6       b7       b8       b9       b10      b11

data[ 6] = (pcr >> 34) & 0xff;
data[ 7] = (pcr >> 26) & 0xff;
data[ 8] = (pcr >> 18) & 0xff;
data[ 9] = (pcr >> 10) & 0xff;
data[10] = 0x7e | ((pcr & (1 << 9)) >> 2) | ((pcr & (1 << 8)) >> 8);
data[11] = pcr & 0xff;
Overcrop answered 1/6, 2011 at 13:28 Comment(5)
Giving it a closer look I noticed that my bitshifting for data[10] wasn't quite right either, I've fixed it here :) I've never noticed that before, probably due to decoders not paying much attention to the less significant bits...Overcrop
Hi Schieferstapel,Thank you :)Sexivalent
It is important to note that a simple bitshift (as shown in the first part of the answer) will give incorrect results, as the PCR is given as (PCR_base * 300) + PCR_extSalvador
paintcan: I would agree that it's not possible to convert from a 27 MHz reference to a 90 kHz reference with a bitshift, but in this case there's no 27 MHz clock, only the 90 kHz PTS value.Calathus
Actually the PCR value could be obtained by multiplying the PTS (and DTS if used) by 300. Normally they share the same clock source.Bultman
R
3

The answer of @schieferstapel is correct. I am only adding one more note here which refers to an exception.

There are times when B frames arrives after (who's PTS is less than) P frames. so PTS can be non-linear if every picture is stamped with PTS value. Whereas, PCR must be incrementally linear.

So in the above situation, you must try to either omit B frames or make relevant calculation when putting PCR values. Also, if this is hardware playouts, it is advisable that PCR should be slightly ahead (lesser by 400 ms or so) than PTS of corresponding I frames.

Ronni answered 27/11, 2011 at 11:37 Comment(1)
Normally the frames carry their corresponding DTS timestamp (decoding time-stamp) that should be used to decode/prepare them before presenting them at PTS. This is critical specially for video since the decoding operation is time consuming.Bultman
H
0

the PCR contains 33(PCR_Base)+6(PCR_const)+9(PCR_Ext) number of bits and also it states that the first 33 bits are based on a 90 kHz clock while the last 9 are based on a 27 MHz clock.PCR_const = 0x3F PCR_Ext=0 PCR_Base=pts/dts

Below code is easy understand.

    PCR_Ext = 0;
    PCR_Const = 0x3F;
    int64_t pcrv = PCR_Ext & 0x1ff;
    pcrv |= (PCR_Const << 9) & 0x7E00;
    pcrv |= (PCR_Base << 15) & 0xFFFFFFFF8000LL;

    pp = (char*)&pcrv;
    data[ 6] = pp[5];
    data[ 7] = pp[4];
    data[ 8] = pp[3];
    data[ 9] = pp[2];
    data[10] = pp[1];
    data[11] = pp[0];
Heelpiece answered 12/10, 2016 at 7:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.