Hi, Patrick Fischer wrote: >>> From standard, I miss the following checks: >> >> - Is there payload in this TS packet? >> - Does a new PES packet start with this TS packet? >> (payload_unit_start_indicator) >> - Does the payload start with 00 00 01 PES header prefix? >> - Does the stream_id refer to an A/V stream with full headers? >> (well, if VideoPid is valid, this should be expected) >> - Is the PTS field present in the PES header? >> >> With these assumptions, Data+4+off points to the PES header, and >> PESheader+9 points to the PTS. >> >> Cheers, >> >> Udo >> >> > Hello at the WE I have rewritten my PTSReceiver. It works with more > then 3 PID. > > #define TS_SIZE 188 > #define PAY_START 0x40 // 0100 0000 > #define ADAPT_FIELD 0x20 // 0010 0000 > #define PAYLOAD 0x10 // 0001 0000 > #define PTS_DTS_FLAGS 0xC0 // 1100 0000 > > //See spec. at ISO/IEC 12818-1 > // TS Page 42 > // PES Header Page 142 > void cPTSReceiver::Receive(uchar *Data, int Length) > { > char spts[20]; > > // TS packet length: TS_SIZE > if (Length == TS_SIZE) > { > int pid = ((Data[1] & 0x1f) << 8) | (Data[2]); > if (!(Data[3] & PAYLOAD)) > { > return;//no payload avalible > } > uint8_t off = 0; > if (Data[3] & ADAPT_FIELD) { > off = Data[4] + 1;//Skip adaptrer_field() > } > > if (Data[1] & PAY_START)//if payload_unit_start_indicator is 1, > then a new PES Packet start > { > uint8_t *sb = Data + 4 + off; //pointer to data_byte > (payload) > if ((sb[0] << 16 | sb[1] << 8 | sb[2] )!= > 0x000001){//packet_start_code_prefix return; > } > if (sb[7] & PTS_DTS_FLAGS) //the 8 byte of the PES > packet are 7 Flags > { > uint64_t frame_pts = (uint64_t)floor( > (trans_pts_dts(sb+9)/90000.)+0.5 ); ^^^^^^^ looks like frame_pts contains complete seconds (90000 pts = 1 s) Try this to get frames (90000 pts = 25 frames): uint64_t frame_pts = trans_pts_dts(sb+9) / 3600; > frameToTime(frame_pts,spts); > printf("pid:%d vpts : %s\t %d \n",pid,spts,frame_pts); > } > } > } > } > > uint64_t cPTSReceiver::trans_pts_dts(uint8_t *pts) > { > uint64_t wts; > > wts = ((uint64_t)((pts[0] & 0x0E) << 5) | > ((pts[1] & 0xFC) >> 2)) << 24; > wts |= (((pts[1] & 0x03) << 6) | > ((pts[2] & 0xFC) >> 2)) << 16; > wts |= (((pts[2] & 0x02) << 6) | > ((pts[3] & 0xFE) >> 1)) << 8; > wts |= (((pts[3] & 0x01) << 7) | > ((pts[4] & 0xFE) >> 1)); > return wts; > } > > > void cPTSReceiver::frameToTime(uint64_t frame_pts,char* timecode) > { > int h,min, sec, res; > h=min=sec=res=0; > if (frame_pts != 0) > { > h = frame_pts/(25 * 60 * 60); > min = frame_pts/(25 * 60) - h * 60; > sec = frame_pts/25 - min*60 -h*3600 ; > res = frame_pts - h*3600 *25 -min * 60 *25 - sec *25; > } > sprintf(timecode,"%d:%d:%d.%d\n",h,min,sec,res); > return; > } > > It seems to work but I have a problem. > ....... > pid:545 vpts : 0:40:3.3 60078 > pid:561 vpts : 0:29:36.0 44400 > pid:545 vpts : 0:40:3.3 60078 > pid:561 vpts : 0:29:36.0 44400 > pid:561 vpts : 0:29:36.0 44400 > pid:545 vpts : 0:40:3.3 60078 > pid:545 vpts : 0:40:3.3 60078 > ..... > I get double entries for each PID. > If I understand, "payload_unit_start_indicator" should be 1 for every > new Packet. > Should this prevent that I get doubel PTS? See above. But keep in mind, that video frames and associated PTS values appear in decoding order while the PTS values are used to order the decoded frames chronologically for sending them on screen. An example: The video sequence (frame type + pts value) B0 B1 I2 B3 B4 P5 B6 B7 P8 with rising pts values (= display order) will be broadcast like that (decoding order): I2 B0 B1 P5 B3 B4 P8 B6 B7 So you'll see the PTS values jump back and forth. Bye. -- Dipl.-Inform. (FH) Reinhard Nissl mailto:rnissl@xxxxxx