Hello I have a couple of questions.
1. whats the differents between cReceiver and cFilter? I was first exposed the cFilter is set for only one PID and the cReceiver can get all Pakets from the whole stream. But now I think the cReceiver can't get all the Pakets because the bandwidth of the pci/usb/.. can't be enough. So what is the differents? Im not so long in this list but I think this question sould picked up in the PLUGINS.html
2. I want to get the PTS from the current V-PID. I have looked at the femon Plugin. This use a cReceiver which gives me an repacked TS with 188byts. I have surched for a Spec. which gives me more informations about the 188Byts. The first 16bit (12bit used) are the PID 8bit are the (PAYLOAD/ADAPT_FIELD)(don't know what it is) 8bit some kind of offset ......
then femon sets a pointer to the receved paket+offset (named sb) next femon sets a new pointer to sb + sb[8] + 9 (named pay) after all pay shows to the video, audio or AC3 data.
But how to get the PTS?
3. I want to get all PTS from all V-PID's on the transponder. Is it possible?
Yours sincerely Patrick
I make my own answer :-)
- I want to get the PTS from the current V-PID. I have looked at the
femon Plugin. This use a cReceiver which gives me an repacked TS with 188byts. I have surched for a Spec. which gives me more informations about the 188Byts. The first 16bit (12bit used) are the PID 8bit are the (PAYLOAD/ADAPT_FIELD)(don't know what it is) 8bit some kind of offset ......
then femon sets a pointer to the receved paket+offset (named sb) next femon sets a new pointer to sb + sb[8] + 9 (named pay) after all pay shows to the video, audio or AC3 data.
But how to get the PTS?
at this way I get a PTS for one PID. Now I need to deal more with cReceiver and more PIDs.
Found at libdvbmpeg:
uint64_t cMyReceiver::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 cMyReceiver::Receive(uchar *Data, int Length) { int pid = ((Data[1] & 0x1f) << 8) | (Data[2]); if (pid == m_VideoPid) { uint8_t off = 0; if (Data[3] & ADAPT_FIELD) { off = Data[4] + 1; } printf("vpts : %fs\n",trans_pts_dts( (uint8_t*)(Data + 4 + off)+9)/90000.); } }
It works fine.
Patrick Fischer wrote:
void cMyReceiver::Receive(uchar *Data, int Length) { int pid = ((Data[1] & 0x1f) << 8) | (Data[2]); if (pid == m_VideoPid) { uint8_t off = 0; if (Data[3] & ADAPT_FIELD) { off = Data[4] + 1; } printf("vpts : %fs\n",trans_pts_dts( (uint8_t*)(Data + 4 + off)+9)/90000.); } }
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
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
Thanks!!! Now I know what to do at this WE. :-)
Patrick
Hello
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 ); 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?
Yours sincerely Patrick
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.
Patrick Fischer wrote:
- I want to get the PTS from the current V-PID. I have looked at the
femon Plugin. This use a cReceiver which gives me an repacked TS with 188byts. I have surched for a Spec. which gives me more informations about the 188Byts. The first 16bit (12bit used) are the PID 8bit are the (PAYLOAD/ADAPT_FIELD)(don't know what it is) 8bit some kind of offset ......
The mpeg-TS format (and all the other mpeg sream formats) is specified in ISO/IEC 13181-1.
The difficult thing about these mpeg formats is that often unused parts of the headers get skipped, which causes all data behind the hidden part to move forward. In case of TS, the layout changes depending on whether the adaption field exists or not. (ADAPT_FIELD flag, officially called adaption_field_control)
TS packets can contain an adaption field and/or payload, depending on adaption_field_control. If the adaption field exists, its first byte is adaption_field_length, your 'some kind of offset'. Payload will be right after the adaption field, if present, and is usually a PES stream.
However, the PTS is not in the TS headers. The PTS first appears in the PES packet headers. Not every PES header has a PTS entry, you have to check the stream_id and the PTS_DTS_flags field...
- I want to get all PTS from all V-PID's on the transponder. Is it
possible?
You would have to receive all the video streams of that transponder at the same time. May cause trouble with the PID filters and with the data throughput.
Cheers,
Udo
Udo Richter schrieb:
Patrick Fischer wrote:
- I want to get the PTS from the current V-PID. I have looked at the
femon Plugin. This use a cReceiver which gives me an repacked TS with 188byts. I have surched for a Spec. which gives me more informations about the 188Byts. The first 16bit (12bit used) are the PID 8bit are the (PAYLOAD/ADAPT_FIELD)(don't know what it is) 8bit some kind of offset ......
The mpeg-TS format (and all the other mpeg sream formats) is specified in ISO/IEC 13181-1.
The difficult thing about these mpeg formats is that often unused parts of the headers get skipped, which causes all data behind the hidden part to move forward. In case of TS, the layout changes depending on whether the adaption field exists or not. (ADAPT_FIELD flag, officially called adaption_field_control)
TS packets can contain an adaption field and/or payload, depending on adaption_field_control. If the adaption field exists, its first byte is adaption_field_length, your 'some kind of offset'. Payload will be right after the adaption field, if present, and is usually a PES stream.
However, the PTS is not in the TS headers. The PTS first appears in the PES packet headers. Not every PES header has a PTS entry, you have to check the stream_id and the PTS_DTS_flags field...
Thanks. So i have to check more then the ADAPT_FIELD. I will fix my version.
- I want to get all PTS from all V-PID's on the transponder. Is it
possible?
You would have to receive all the video streams of that transponder at the same time. May cause trouble with the PID filters and with the data throughput.
I think the PID's will not make problems. Each PID is unique for a videostream of the transponder. But with the throughput you are rigth. I need an other idea. Maybe I can listen to 2-3 PID's and skip always one of them.
Patrick
Hello I have a couple of questions.
- whats the differents between cReceiver and cFilter?
I was first exposed the cFilter is set for only one PID and the cReceiver can get all Pakets from the whole stream. But now I think the cReceiver can't get all the Pakets because the bandwidth of the pci/usb/.. can't be enough. So what is the differents? Im not so long in this list but I think this question sould picked up in the PLUGINS.html
This might be a FAQ, so a longer answer:
A cFilter is a layer above cReceiver and has a much more specific purpose then a cReceiver.
With DVB, you have different sorts of data: -Audio, Video, Teletext, ... -Program Specific information (PSI) aka Service Information (SI) (such as EPG) All data is delivered in 188 byte TS packets. With a cReceiver, you request one or more transport streams, identified by their pids. For audio or video, you unpack the payload and then you have a PES stream (once again with a header and a payload, but much larger packet size).
Program specific information is different. It is formatted in tables (PAT, PMT, CAT, EIT, NIT, SDT, TOT, TDT, the first three defined in iso 13818-1, the latter in ETSI EN 300 468). These tables are split into sections. (If you read the standards, you find the definitions of the _sections_, the table is merely the collection of all sections it is split into. VDR, in pat.c, eit.c, sdt.c, always deals with the sections.) Every table/section has a specific table ID. Sections are put in the payload of the TS packets, split if necessary. See section 5.1.2 of 300 468 for details. These transport streams containing the SI sections are broadcast mostly at predefined PIDs. E.g. PID 0x00 is always the PAT. (see section 5.1.3) The PMT pids are not defined, they can be found in the PAT. Now you can construct a cReceiver, get the TS packets, unpack them, buffer them, get the starting point of a section, and extract the sections. Or you let the driver do that for you and construct a cFilter, which takes the PID and the table ID (confusingly called Tid in the code, which also stands for Transport Stream ID in other places)
- I want to get the PTS from the current V-PID. I have looked at the
femon Plugin. This use a cReceiver which gives me an repacked TS with 188byts.
I have surched for a Spec. which gives me more informations about the 188Byts.
You have that version of ISO-13818-1 circulating on the internet? Google gave me http://www.le-hacker.org/hacks/mpeg-drafts/is138181.pdf if you do not.
The first 16bit (12bit used) are the PID 8bit are the (PAYLOAD/ADAPT_FIELD)(don't know what it is) 8bit some kind of offset ......
then femon sets a pointer to the receved paket+offset (named sb) next femon sets a new pointer to sb + sb[8] + 9 (named pay) after all pay shows to the video, audio or AC3 data.
But how to get the PTS?
I know you know my MHP plugin. In libmhpoutput/mpegpes-common, there is a file pesheaders.h which contains a definitions for PES header structures. The corresponding function PESBuilder::SendData where data is wrapped in PES packets is unfortunately not as easy to read. If I remember correctly, the bitstreamout plugin contains optimized code to retrieve the PTS.
Marcel
- I want to get all PTS from all V-PID's on the transponder. Is it
possible?
Yours sincerely Patrick
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr