Message ID | 20220404095312.21140-1-jeebjp@gmail.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel] avformat/mpegts: set data broadcast streams as such | expand |
Context | Check | Description |
---|---|---|
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | fail | Make fate failed |
andriy/make_aarch64_jetson | success | Make finished |
andriy/make_fate_aarch64_jetson | fail | Make fate failed |
andriy/make_armv7_RPi4 | success | Make finished |
andriy/make_fate_armv7_RPi4 | fail | Make fate failed |
On Mon, Apr 4, 2022 at 12:53 PM Jan Ekström <jeebjp@gmail.com> wrote: > > From: Jan Ekström <jan.ekstrom@24i.com> > > Additionally, they should not be probed, as this is essentially > various types of binary data. > > Signed-off-by: Jan Ekström <jan.ekstrom@24i.com> > --- The test file referenced with this sort of signaling is available at: https://megumin.fushizen.eu/samples/2022-02-04-radio_with_data_stream/mpegts_sdt_data_stream.ts Jan
As I posted a patch on Apr. 3rd, you should use "desc_end" rather than "p_end" for get16() or get8() to parse each descriptor. On 2022/04/04 18:53, Jan Ekström wrote: > From: Jan Ekström <jan.ekstrom@24i.com> > > Additionally, they should not be probed, as this is essentially > various types of binary data. > > Signed-off-by: Jan Ekström <jan.ekstrom@24i.com> > --- > libavformat/mpegts.c | 48 +++++++++++++++++++++ > tests/fate/mpegts.mak | 3 ++ > tests/ref/fate/mpegts-probe-sdt-data-stream | 14 ++++++ > 3 files changed, 65 insertions(+) > create mode 100644 tests/ref/fate/mpegts-probe-sdt-data-stream > > diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c > index da77b50669..3788faf848 100644 > --- a/libavformat/mpegts.c > +++ b/libavformat/mpegts.c > @@ -2512,6 +2512,13 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len > } > } > p = desc_list_end; > + > + if (!ts->pkt && (stream_type >= 0x80 && stream_type <= 0xFF) && > + st->codecpar->codec_id == AV_CODEC_ID_NONE) > + // if we are reading headers, and still have a user private stream > + // with no proper codec set, do not stop reading at PMT. Data > + // streams are marked within SDT. > + ts->stop_parse = 0; > } > > if (!ts->pids[pcr_pid]) > @@ -2691,6 +2698,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len > if (val < 0) > return; > for (;;) { > + struct Program *program = NULL; > sid = get16(&p, p_end); > if (sid < 0) > break; > @@ -2704,6 +2712,15 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len > desc_list_end = p + desc_list_len; > if (desc_list_end > p_end) > break; > + > + program = get_program(ts, sid); > + > + if (!ts->pkt && program && program->pmt_found) > + // if during header reading we have already received a PMT for > + // this program and now have received an SDT for it, stop further > + // reading at this point. > + ts->stop_parse = 2; > + > for (;;) { > desc_tag = get8(&p, desc_list_end); > if (desc_tag < 0) > @@ -2736,6 +2753,37 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len > av_free(name); > av_free(provider_name); > break; > + case 0x64: /* ETSI data broadcast descriptor; EN 300 468 6.2.11 */ > + { > + AVStream *st = NULL; > + FFStream *sti = NULL; > + > + uint16_t data_broadcast_id = get16(&p, p_end); // TS 101 162 s/p_end/desc_end/ > + uint8_t component_tag = get8(&p, p_end); s/p_end/desc_end/ > + if (!component_tag) > + // no stream mapping according to component_tag > + break; > + > + av_log(ts->stream, AV_LOG_TRACE, > + "data broadcast id: %d, component tag: %d\n", > + data_broadcast_id, component_tag); > + > + if (!program) > + break; > + > + st = find_matching_stream(ts, 0, sid, component_tag + 1, 0, > + program); > + if (!st) > + break; > + > + sti = ffstream(st); > + > + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; > + st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; > + sti->request_probe = sti->need_parsing = 0; > + sti->need_context_update = 1; > + break; > + } > default: > break; > } > diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak > index bbcbfc47b2..ae21ee87d0 100644 > --- a/tests/fate/mpegts.mak > +++ b/tests/fate/mpegts.mak > @@ -19,6 +19,9 @@ FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS) += fate-mpegts-probe-pmt-merge > fate-mpegts-probe-pmt-merge: SRC = $(TARGET_SAMPLES)/mpegts/pmtchange.ts > fate-mpegts-probe-pmt-merge: CMD = run $(PROBE_CODEC_NAME_COMMAND) -merge_pmt_versions 1 -i "$(SRC)" > > +FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, MP2) += fate-mpegts-probe-sdt-data-stream > +fate-mpegts-probe-sdt-data-stream: SRC = $(TARGET_SAMPLES)/mpegts/mpegts_sdt_data_stream.ts > +fate-mpegts-probe-sdt-data-stream: CMD = run $(PROBE_CODEC_NAME_COMMAND) -i "$(SRC)" > > FATE_SAMPLES_FFPROBE += $(FATE_MPEGTS_PROBE-yes) > > diff --git a/tests/ref/fate/mpegts-probe-sdt-data-stream b/tests/ref/fate/mpegts-probe-sdt-data-stream > new file mode 100644 > index 0000000000..0b8e90962f > --- /dev/null > +++ b/tests/ref/fate/mpegts-probe-sdt-data-stream > @@ -0,0 +1,14 @@ > +[PROGRAM] > +[STREAM] > +codec_name=mp2 > +[/STREAM] > +[STREAM] > +codec_name=bin_data > +[/STREAM] > +[/PROGRAM] > +[STREAM] > +codec_name=mp2 > +[/STREAM] > +[STREAM] > +codec_name=bin_data > +[/STREAM]
... and, it is better to check broken packet. On 2022/04/05 1:04, TADANO Tokumei wrote: > As I posted a patch on Apr. 3rd, you should use "desc_end" rather than "p_end" > for get16() or get8() to parse each descriptor. > > On 2022/04/04 18:53, Jan Ekström wrote: >> From: Jan Ekström <jan.ekstrom@24i.com> >> >> Additionally, they should not be probed, as this is essentially >> various types of binary data. >> >> Signed-off-by: Jan Ekström <jan.ekstrom@24i.com> >> --- >> libavformat/mpegts.c | 48 +++++++++++++++++++++ >> tests/fate/mpegts.mak | 3 ++ >> tests/ref/fate/mpegts-probe-sdt-data-stream | 14 ++++++ >> 3 files changed, 65 insertions(+) >> create mode 100644 tests/ref/fate/mpegts-probe-sdt-data-stream >> >> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c >> index da77b50669..3788faf848 100644 >> --- a/libavformat/mpegts.c >> +++ b/libavformat/mpegts.c >> @@ -2512,6 +2512,13 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >> } >> } >> p = desc_list_end; >> + >> + if (!ts->pkt && (stream_type >= 0x80 && stream_type <= 0xFF) && >> + st->codecpar->codec_id == AV_CODEC_ID_NONE) >> + // if we are reading headers, and still have a user private stream >> + // with no proper codec set, do not stop reading at PMT. Data >> + // streams are marked within SDT. >> + ts->stop_parse = 0; >> } >> if (!ts->pids[pcr_pid]) >> @@ -2691,6 +2698,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >> if (val < 0) >> return; >> for (;;) { >> + struct Program *program = NULL; >> sid = get16(&p, p_end); >> if (sid < 0) >> break; >> @@ -2704,6 +2712,15 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >> desc_list_end = p + desc_list_len; >> if (desc_list_end > p_end) >> break; >> + >> + program = get_program(ts, sid); >> + >> + if (!ts->pkt && program && program->pmt_found) >> + // if during header reading we have already received a PMT for >> + // this program and now have received an SDT for it, stop further >> + // reading at this point. >> + ts->stop_parse = 2; >> + >> for (;;) { >> desc_tag = get8(&p, desc_list_end); >> if (desc_tag < 0) >> @@ -2736,6 +2753,37 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >> av_free(name); >> av_free(provider_name); >> break; >> + case 0x64: /* ETSI data broadcast descriptor; EN 300 468 6.2.11 */ >> + { >> + AVStream *st = NULL; >> + FFStream *sti = NULL; >> + >> + uint16_t data_broadcast_id = get16(&p, p_end); // TS 101 162 > > s/p_end/desc_end/ if (data_broadcast_id < 0) break; > >> + uint8_t component_tag = get8(&p, p_end); > > s/p_end/desc_end/ > >> + if (!component_tag) if (component_tag <= 0) >> + // no stream mapping according to component_tag >> + break; >> + >> + av_log(ts->stream, AV_LOG_TRACE, >> + "data broadcast id: %d, component tag: %d\n", >> + data_broadcast_id, component_tag); >> + >> + if (!program) >> + break; >> + >> + st = find_matching_stream(ts, 0, sid, component_tag + 1, 0, >> + program); >> + if (!st) >> + break; >> + >> + sti = ffstream(st); >> + >> + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; >> + st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; >> + sti->request_probe = sti->need_parsing = 0; >> + sti->need_context_update = 1; >> + break; >> + } >> default: >> break; >> } >> diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak >> index bbcbfc47b2..ae21ee87d0 100644 >> --- a/tests/fate/mpegts.mak >> +++ b/tests/fate/mpegts.mak >> @@ -19,6 +19,9 @@ FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS) += fate-mpegts-probe-pmt-merge >> fate-mpegts-probe-pmt-merge: SRC = $(TARGET_SAMPLES)/mpegts/pmtchange.ts >> fate-mpegts-probe-pmt-merge: CMD = run $(PROBE_CODEC_NAME_COMMAND) -merge_pmt_versions 1 -i "$(SRC)" >> +FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, MP2) += fate-mpegts-probe-sdt-data-stream >> +fate-mpegts-probe-sdt-data-stream: SRC = $(TARGET_SAMPLES)/mpegts/mpegts_sdt_data_stream.ts >> +fate-mpegts-probe-sdt-data-stream: CMD = run $(PROBE_CODEC_NAME_COMMAND) -i "$(SRC)" >> FATE_SAMPLES_FFPROBE += $(FATE_MPEGTS_PROBE-yes) >> diff --git a/tests/ref/fate/mpegts-probe-sdt-data-stream b/tests/ref/fate/mpegts-probe-sdt-data-stream >> new file mode 100644 >> index 0000000000..0b8e90962f >> --- /dev/null >> +++ b/tests/ref/fate/mpegts-probe-sdt-data-stream >> @@ -0,0 +1,14 @@ >> +[PROGRAM] >> +[STREAM] >> +codec_name=mp2 >> +[/STREAM] >> +[STREAM] >> +codec_name=bin_data >> +[/STREAM] >> +[/PROGRAM] >> +[STREAM] >> +codec_name=mp2 >> +[/STREAM] >> +[STREAM] >> +codec_name=bin_data >> +[/STREAM] > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Ah, the variables should be int. On 2022/04/05 1:16, TADANO Tokumei wrote: > ... and, it is better to check broken packet. > > On 2022/04/05 1:04, TADANO Tokumei wrote: >> As I posted a patch on Apr. 3rd, you should use "desc_end" rather than "p_end" >> for get16() or get8() to parse each descriptor. >> >> On 2022/04/04 18:53, Jan Ekström wrote: >>> From: Jan Ekström <jan.ekstrom@24i.com> >>> >>> Additionally, they should not be probed, as this is essentially >>> various types of binary data. >>> >>> Signed-off-by: Jan Ekström <jan.ekstrom@24i.com> >>> --- >>> libavformat/mpegts.c | 48 +++++++++++++++++++++ >>> tests/fate/mpegts.mak | 3 ++ >>> tests/ref/fate/mpegts-probe-sdt-data-stream | 14 ++++++ >>> 3 files changed, 65 insertions(+) >>> create mode 100644 tests/ref/fate/mpegts-probe-sdt-data-stream >>> >>> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c >>> index da77b50669..3788faf848 100644 >>> --- a/libavformat/mpegts.c >>> +++ b/libavformat/mpegts.c >>> @@ -2512,6 +2512,13 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >>> } >>> } >>> p = desc_list_end; >>> + >>> + if (!ts->pkt && (stream_type >= 0x80 && stream_type <= 0xFF) && >>> + st->codecpar->codec_id == AV_CODEC_ID_NONE) >>> + // if we are reading headers, and still have a user private stream >>> + // with no proper codec set, do not stop reading at PMT. Data >>> + // streams are marked within SDT. >>> + ts->stop_parse = 0; >>> } >>> if (!ts->pids[pcr_pid]) >>> @@ -2691,6 +2698,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >>> if (val < 0) >>> return; >>> for (;;) { >>> + struct Program *program = NULL; >>> sid = get16(&p, p_end); >>> if (sid < 0) >>> break; >>> @@ -2704,6 +2712,15 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >>> desc_list_end = p + desc_list_len; >>> if (desc_list_end > p_end) >>> break; >>> + >>> + program = get_program(ts, sid); >>> + >>> + if (!ts->pkt && program && program->pmt_found) >>> + // if during header reading we have already received a PMT for >>> + // this program and now have received an SDT for it, stop further >>> + // reading at this point. >>> + ts->stop_parse = 2; >>> + >>> for (;;) { >>> desc_tag = get8(&p, desc_list_end); >>> if (desc_tag < 0) >>> @@ -2736,6 +2753,37 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len >>> av_free(name); >>> av_free(provider_name); >>> break; >>> + case 0x64: /* ETSI data broadcast descriptor; EN 300 468 6.2.11 */ >>> + { >>> + AVStream *st = NULL; >>> + FFStream *sti = NULL; >>> + >>> + uint16_t data_broadcast_id = get16(&p, p_end); // TS 101 162 >> >> s/p_end/desc_end/ int data_broadcast_id = get16(&p, desc_end); > if (data_broadcast_id < 0) > break; > >> >>> + uint8_t component_tag = get8(&p, p_end); >> >> s/p_end/desc_end/ int component_tag = get8(&p, desc_end); >> >>> + if (!component_tag) > if (component_tag <= 0) > >>> + // no stream mapping according to component_tag >>> + break; >>> + >>> + av_log(ts->stream, AV_LOG_TRACE, >>> + "data broadcast id: %d, component tag: %d\n", >>> + data_broadcast_id, component_tag); >>> + >>> + if (!program) >>> + break; >>> + >>> + st = find_matching_stream(ts, 0, sid, component_tag + 1, 0, >>> + program); >>> + if (!st) >>> + break; >>> + >>> + sti = ffstream(st); >>> + >>> + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; >>> + st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; >>> + sti->request_probe = sti->need_parsing = 0; >>> + sti->need_context_update = 1; >>> + break; >>> + } >>> default: >>> break; >>> } >>> diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak >>> index bbcbfc47b2..ae21ee87d0 100644 >>> --- a/tests/fate/mpegts.mak >>> +++ b/tests/fate/mpegts.mak >>> @@ -19,6 +19,9 @@ FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS) += fate-mpegts-probe-pmt-merge >>> fate-mpegts-probe-pmt-merge: SRC = $(TARGET_SAMPLES)/mpegts/pmtchange.ts >>> fate-mpegts-probe-pmt-merge: CMD = run $(PROBE_CODEC_NAME_COMMAND) -merge_pmt_versions 1 -i "$(SRC)" >>> +FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, MP2) += fate-mpegts-probe-sdt-data-stream >>> +fate-mpegts-probe-sdt-data-stream: SRC = $(TARGET_SAMPLES)/mpegts/mpegts_sdt_data_stream.ts >>> +fate-mpegts-probe-sdt-data-stream: CMD = run $(PROBE_CODEC_NAME_COMMAND) -i "$(SRC)" >>> FATE_SAMPLES_FFPROBE += $(FATE_MPEGTS_PROBE-yes) >>> diff --git a/tests/ref/fate/mpegts-probe-sdt-data-stream b/tests/ref/fate/mpegts-probe-sdt-data-stream >>> new file mode 100644 >>> index 0000000000..0b8e90962f >>> --- /dev/null >>> +++ b/tests/ref/fate/mpegts-probe-sdt-data-stream >>> @@ -0,0 +1,14 @@ >>> +[PROGRAM] >>> +[STREAM] >>> +codec_name=mp2 >>> +[/STREAM] >>> +[STREAM] >>> +codec_name=bin_data >>> +[/STREAM] >>> +[/PROGRAM] >>> +[STREAM] >>> +codec_name=mp2 >>> +[/STREAM] >>> +[STREAM] >>> +codec_name=bin_data >>> +[/STREAM] >> _______________________________________________ >> ffmpeg-devel mailing list >> ffmpeg-devel@ffmpeg.org >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel >> >> To unsubscribe, visit link above, or email >> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On Mon, Apr 4, 2022 at 7:04 PM TADANO Tokumei <aimingoff@pc.nifty.jp> wrote: > > As I posted a patch on Apr. 3rd, you should use "desc_end" rather than "p_end" > for get16() or get8() to parse each descriptor. > Yes, I had noticed and planned to look into those patches, but did not have the time to do that yet. Also FYI, this mailing list utilizes bottom posting, not top posting. Jan
On Mon, Apr 4, 2022 at 7:32 PM TADANO Tokumei <aimingoff@pc.nifty.jp> wrote: > > Ah, the variables should be int. > > On 2022/04/05 1:16, TADANO Tokumei wrote: > > ... and, it is better to check broken packet. > > Yes. I guess I'll swap those for ints, although I like having the original unsigned sizes :) . I think alternatively it could be checked whether there is enough data before hand, since the only error seems to be if there is not enough data available. In this case it would be three bytes I think, 16+8 bits. Jan
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index da77b50669..3788faf848 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -2512,6 +2512,13 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len } } p = desc_list_end; + + if (!ts->pkt && (stream_type >= 0x80 && stream_type <= 0xFF) && + st->codecpar->codec_id == AV_CODEC_ID_NONE) + // if we are reading headers, and still have a user private stream + // with no proper codec set, do not stop reading at PMT. Data + // streams are marked within SDT. + ts->stop_parse = 0; } if (!ts->pids[pcr_pid]) @@ -2691,6 +2698,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (val < 0) return; for (;;) { + struct Program *program = NULL; sid = get16(&p, p_end); if (sid < 0) break; @@ -2704,6 +2712,15 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len desc_list_end = p + desc_list_len; if (desc_list_end > p_end) break; + + program = get_program(ts, sid); + + if (!ts->pkt && program && program->pmt_found) + // if during header reading we have already received a PMT for + // this program and now have received an SDT for it, stop further + // reading at this point. + ts->stop_parse = 2; + for (;;) { desc_tag = get8(&p, desc_list_end); if (desc_tag < 0) @@ -2736,6 +2753,37 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len av_free(name); av_free(provider_name); break; + case 0x64: /* ETSI data broadcast descriptor; EN 300 468 6.2.11 */ + { + AVStream *st = NULL; + FFStream *sti = NULL; + + uint16_t data_broadcast_id = get16(&p, p_end); // TS 101 162 + uint8_t component_tag = get8(&p, p_end); + if (!component_tag) + // no stream mapping according to component_tag + break; + + av_log(ts->stream, AV_LOG_TRACE, + "data broadcast id: %d, component tag: %d\n", + data_broadcast_id, component_tag); + + if (!program) + break; + + st = find_matching_stream(ts, 0, sid, component_tag + 1, 0, + program); + if (!st) + break; + + sti = ffstream(st); + + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; + sti->request_probe = sti->need_parsing = 0; + sti->need_context_update = 1; + break; + } default: break; } diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak index bbcbfc47b2..ae21ee87d0 100644 --- a/tests/fate/mpegts.mak +++ b/tests/fate/mpegts.mak @@ -19,6 +19,9 @@ FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS) += fate-mpegts-probe-pmt-merge fate-mpegts-probe-pmt-merge: SRC = $(TARGET_SAMPLES)/mpegts/pmtchange.ts fate-mpegts-probe-pmt-merge: CMD = run $(PROBE_CODEC_NAME_COMMAND) -merge_pmt_versions 1 -i "$(SRC)" +FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, MP2) += fate-mpegts-probe-sdt-data-stream +fate-mpegts-probe-sdt-data-stream: SRC = $(TARGET_SAMPLES)/mpegts/mpegts_sdt_data_stream.ts +fate-mpegts-probe-sdt-data-stream: CMD = run $(PROBE_CODEC_NAME_COMMAND) -i "$(SRC)" FATE_SAMPLES_FFPROBE += $(FATE_MPEGTS_PROBE-yes) diff --git a/tests/ref/fate/mpegts-probe-sdt-data-stream b/tests/ref/fate/mpegts-probe-sdt-data-stream new file mode 100644 index 0000000000..0b8e90962f --- /dev/null +++ b/tests/ref/fate/mpegts-probe-sdt-data-stream @@ -0,0 +1,14 @@ +[PROGRAM] +[STREAM] +codec_name=mp2 +[/STREAM] +[STREAM] +codec_name=bin_data +[/STREAM] +[/PROGRAM] +[STREAM] +codec_name=mp2 +[/STREAM] +[STREAM] +codec_name=bin_data +[/STREAM]