mpeg2ts There is... In the file format pcr and pts The concept of , The meaning of the code is as follows :
PCR(Program Clock Reference)—— The time tag indicating the instantaneous value of the system clock itself is called the program reference clock tag (PCR).
PTS(Presentation Time Stamp)—— The time stamp indicating the display time of audio and video is called display time stamp (PTS).
More specific meanings of the two can be found online , This is no longer the focus of this post . The theme of this post is : Using encoded frames bitstream The time stamp carried with it , How to convert ts In the document pcr and pts value .
1. A typical video and audio ts Data packets :
AAC: 47 41 E1 3F 07 10 00 F9 F2 B6 FE B3 00 00 01 C0 01 6A 84 80 05 21 07 CF CA DB ...(bitstream)...
AVC: 47 41 E2 3D 07 10 00 F9 F2 B6 FE B3 00 00 01 E0 98 65 84 80 05 21 07 CF CA DB ...(bitstream)...
Red Of Six bytes by pcr value (188Bytes Of TS The number of packets is 7 Bytes ), Pink Of Four half bytes by pts value ( The tail of the head , It's followed by coded data ).
2. pcr And pts Algorithm is introduced (pcr_val(48b) and pts[32..30..0](33b))
Two typical examples are as follows :
Timestamp 00:06:04.013(timsUs=364013000) A frame of data , Its pcr Value :00 F9 F2 A9 7E 0D , Its pts[32...0] The value is :21 07 CF CA A5
Timestamp 00:06:04.034(timsUs=364034000) A frame of data , Its pcr Value :00 F9 F6 59 FE CF , Its pts[32...0] The value is :21 07 CF D9 69
among , The encoding module is sent to the packaging module (Android In Chinese, it means MPEG2TSWriter) The time stamp of the encoded frame is not “00:06:04.013” form , It is a long long Integer of type , In microseconds , for example 364013000( representative 364.013 second ), Convert to a format that can be easily recognized by adults (hh:mm:ss) by :00:06:04.013.
Be careful ,ts When packaging , The standard stipulates pcr Values and pts How the bits are arranged ( Refer to the following pcr_val and pts_val Array , I.e. compliance spec Regulations ).
3. timeUs and pcr Between
Forward operation :timeUs -> pcr ( For encapsulation )
float tmp = timeUs / 1000000 + (timeUs % 1000000) / 1000 * 0.001; //timeUs With us In units of ,tmp With s In units of , It is converted into xy.z Format ( The decimal point is placed before the sixth last byte ),xy Is the second value ,z Is the millisecond value
long long pcr = (long long)(tmp * 27000000.0);
long long pcr_low = pcr % 300LL;
long long pcr_high = pcr / 300LL;
unsigned char pcr_val[6]; // To be written ts In the document 6 Byte values
pcr_val[0] = pcr_high>>25;
pcr_val[1] = pcr_high>>17;
pcr_val[2] = pcr_high>>9;
pcr_val[3] = pcr_high>>1;
pcr_val[4] = pcr_high<<7 | pcr_low>>8 | 0x7e;
pcr_val[5] = pcr_low;
Reverse operation :pcr -> timeUs ( Used to get the timestamp when unpacking , From the known ts The file calculates the time stamp of audio and video frames )
long long PCR_LOW = pcr_val[5] + ((pcr_val[4]&0x1)<<8);
long long PCR_HIGH = (pcr_val[4]>>7) + (pcr_val[3]<<1) + (pcr_val[2]<<9) + (pcr_val[1]<<17) + (pcr_val[0]<<25);
long long PCR = PCR_HIGH * 300 + PCR_LOW;
float TMS = PCR / 27000000.0;
4. timeUs and pts Conversion between
Forward operation :timeUs -> pts
long long pts = timeUs * 9LL / 100LL;
unsigned char pts_val[5];
pts_val[0] = 0x20 | (((pts >> 30) & 7) << 1) | 1;
pts_val[1] = (pts >> 22) & 0xff;
pts_val[2] = (((pts >> 15) & 0x7f) << 1) | 1;
pts_val[3] = (pts >> 7) & 0xff;
pts_val[4] = ((pts & 0x7f) << 1) | 1;
Reverse operation :pts -> timeUs
long long PTS = (pts_val[4]>>1) | (pts_val[3]<<7) | (pts_val[2]>>1)<<15 | pts_val[1]<<22 | (pts_val[0]>>1)<<30;
long long TIMEUS = PTS * 100LL / 9LL;
5. complete demo
1 #include <stdio.h> 2 3 int main(void) 4 { 5 long long timeUs = 364034000; 6 7 float tm = timeUs / 1000000 + (timeUs % 1000000) / 1000 * 0.001; 8 long long pcr = (long long)(tm * 27000000.0); 9 long long pcr_low = pcr % 300LL; 10 long long pcr_high = pcr / 300LL; 11 12 unsigned char pcr_val[6]; 13 pcr_val[0] = pcr_high>>25; 14 pcr_val[1] = pcr_high>>17; 15 pcr_val[2] = pcr_high>>9; 16 pcr_val[3] = pcr_high>>1; 17 pcr_val[4] = pcr_high<<7 | pcr_low>>8 | 0x7e; 18 pcr_val[5] = pcr_low; 19 printf("calculate pcr by timeUs!\n"); 20 printf(" timeUs=%lld us, tm=%f s\n", timeUs, tm); 21 printf(" pcr=%llx, pcr_low=%#llx, pcr_high=%#llx\n", pcr, pcr_low, pcr_high); 22 printf(" pcr_val[0-5]: %#x, %#x, %#x, %#x, %#x, %#x\n", pcr_val[0], pcr_val[1], pcr_val[2], pcr_val[3], pcr_val[4], pcr_val[5]); 23 24 long long PCR_LOW = pcr_val[5] + ((pcr_val[4]&0x1)<<8); 25 long long PCR_HIGH = (pcr_val[4]>>7) + (pcr_val[3]<<1) + (pcr_val[2]<<9) + (pcr_val[1]<<17) + (pcr_val[0]<<25); 26 long long PCR = PCR_HIGH * 300 + PCR_LOW; 27 float TMS = PCR / 27000000.0; 28 printf("revert test by pcr_val[0-5]!\n"); 29 printf(" PCR_LOW=%#llx, PCR_HIGH=%#llx, PCR=%#llx, TMS=%f s\n", PCR_LOW, PCR_HIGH, PCR, TMS); 30 31 printf("---------------------------------------------------------------------------\n"); 32 printf("calculate pts by timeUs!\n"); 33 long long pts = timeUs * 9LL / 100LL; 34 unsigned char pts_val[5]; 35 pts_val[0] = 0x20 | (((pts >> 30) & 7) << 1) | 1; 36 pts_val[1] = (pts >> 22) & 0xff; 37 pts_val[2] = (((pts >> 15) & 0x7f) << 1) | 1; 38 pts_val[3] = (pts >> 7) & 0xff; 39 pts_val[4] = ((pts & 0x7f) << 1) | 1; 40 printf(" pts_val[0-4]: %#x, %#x, %#x, %#x, %#x\n", pts_val[0], pts_val[1], pts_val[2], pts_val[3], pts_val[4]); 41 42 printf("revert test by pts_val[0-4]!\n"); 43 long long PTS = (pts_val[4]>>1) | (pts_val[3]<<7) | (pts_val[2]>>1)<<15 | pts_val[1]<<22 | (pts_val[0]>>1)<<30; 44 long long TIMEUS = PTS * 100LL / 9LL; 45 printf(" PTS=%lld, TIMEUS=%lld\n", PTS, TIMEUS); 46 47 long long PTS_VAL = (1LL * pts_val[0]<<32) + (1LL * pts_val[1]<<24) + (1LL * pts_val[2]<<16) + (1LL * pts_val[3]<<8) + (1LL * pts_val[4]); 48 long long PTS1 = ((PTS_VAL>>1)&0x7f) | ((PTS_VAL>>8)&0xff)<<7 | ((PTS_VAL>>(16+1))&0x7f)<<15 | ((PTS_VAL>>24)&0xff)<<22 | ((PTS_VAL>>(32+1))&7)<<30; 49 long long TIMEUS1 = PTS1 * 100LL / 9LL; 50 printf(" PTS1=%lld, TIMEUS1=%lld\n", PTS1, TIMEUS1); 51 52 return 0; 53 }
Running results :