I have prepared a testcase. PMT data comes from org.hbbtv_HTML50420. Please review.
Regards, *Łukasz Krzciuk* Developer Vewd ul. Grabarska 2, Pegaz 2A, 50-079 Wrocław, Polska On Thu, May 10, 2018 at 8:54 PM, Aman Gupta <ffm...@tmm1.net> wrote: > On Thu, May 10, 2018 at 1:46 AM Łukasz Krzciuk <lkrzc...@vewd.com> wrote: > > > Lets skip a testcase. It will be not easy to me to prepare it. > > > It should be simple to extract a small sample containing the PMT. If you > link some larger samples I can help extract the relevant bytes for test > case. > > Aman > > > > > > Regards, > > > > *Łukasz Krzciuk* > > Developer > > > > Vewd > > ul. Grabarska 2 > > <https://maps.google.com/?q=Grabarska+2&entry=gmail&source=g>, Pegaz 2A, > > 50-079 Wrocław, Polska > > > > > > On Thu, May 10, 2018 at 3:09 AM, Michael Niedermayer > > <mich...@niedermayer.cc > > > wrote: > > > > > On Wed, May 09, 2018 at 10:19:26AM +0200, Łukasz Krzciuk wrote: > > > > Any updates on this issue? > > > > > > about adding a testcase ? > > > adding a huge sample file is not possible. > > > It either has to be made smaller or generated by a muxer > > > or last resort, no test > > > > > > [...] > > > -- > > > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC7 > 87040B0FAB > > > > > > The worst form of inequality is to try to make unequal things equal. > > > -- Aristotle > > > > > > _______________________________________________ > > > ffmpeg-devel mailing list > > > ffmpeg-devel@ffmpeg.org > > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > > > > > _______________________________________________ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel >
From 43c48622594b8d868fea5180bc5a4f8b636ea24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Krzciuk?= <lkrzc...@vewd.com> Date: Mon, 14 May 2018 10:16:14 +0200 Subject: [PATCH] fixup! avformat/mpegts: set AV_DISPOSITION_DESCRIPTIONS for OIPF cases --- libavformat/Makefile | 1 + libavformat/tests/descriptor.c | 265 +++++++++++++++++++++++++++++++++++++++++ tests/fate/libavformat.mak | 4 + tests/ref/fate/descriptor | 5 + 4 files changed, 275 insertions(+) create mode 100644 libavformat/tests/descriptor.c create mode 100644 tests/ref/fate/descriptor diff --git a/libavformat/Makefile b/libavformat/Makefile index 3eeca50..373c131 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -635,6 +635,7 @@ TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh TESTPROGS-$(CONFIG_MOV_MUXER) += movenc TESTPROGS-$(CONFIG_NETWORK) += noproxy TESTPROGS-$(CONFIG_SRTP) += srtp +TESTPROGS-$(CONFIG_NETWORK) += descriptor TOOLS = aviocat \ ismindex \ diff --git a/libavformat/tests/descriptor.c b/libavformat/tests/descriptor.c new file mode 100644 index 0000000..a9635cb --- /dev/null +++ b/libavformat/tests/descriptor.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2018 Łukasz Krzciuk + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/intreadwrite.h" +#include "libavutil/md5.h" + +#include "libavformat/avformat.h" +#include "libavformat/mpegts.h" + +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +#define HASH_SIZE 16 + +static const uint8_t aac_extradata[] = { + 0x12, 0x10 +}; +static const uint8_t pmt_editorial_classification[] = { + 0x02, 0xb0, 0x22, 0x00, 0x02, 0xc1, 0x00, 0x00, 0xe0, 0x21, 0xf0, 0x00, + 0x1b, 0xe0, 0x21, 0xf0, 0x00, 0x11, 0xe0, 0x24, 0xf0, 0x0b, 0x7f, 0x05, + 0x06, 0x87, 0x65, 0x6e, 0x67, 0x7c, 0x02, 0x60, 0x00, 0x6f, 0xe1, 0x92, + 0xf7 +}; + +static const char *format = "mp4"; +AVFormatContext *ctx; +uint8_t iobuf[32768]; +AVDictionary *opts; + +const char *cur_name; +int out_size; +struct AVMD5* md5; +uint8_t hash[HASH_SIZE]; + +AVStream *audio_st; +int64_t audio_dts; + +int64_t audio_duration; +int force_iobuf_size; + +static inline int get8(const uint8_t **pp, const uint8_t *p_end) +{ + const uint8_t *p; + int c; + + p = *pp; + if (p >= p_end) + return AVERROR_INVALIDDATA; + c = *p++; + *pp = p; + return c; +} + +static inline int get16(const uint8_t **pp, const uint8_t *p_end) +{ + const uint8_t *p; + int c; + + p = *pp; + if (1 >= p_end - p) + return AVERROR_INVALIDDATA; + c = AV_RB16(p); + p += 2; + *pp = p; + return c; +} + +static void parse_section_header(const uint8_t **pp, const uint8_t *p_end) +{ + get8(pp, p_end); + get8(pp, p_end); + get8(pp, p_end); + get8(pp, p_end); + get8(pp, p_end); + get8(pp, p_end); + + get8(pp, p_end); // tid + get16(pp, p_end); // id + get8(pp, p_end); // version + get8(pp, p_end); // sec_num + get8(pp, p_end); // last_sec_num +} + +static int io_write(void *opaque, uint8_t *buf, int size) +{ + out_size += size; + av_md5_update(md5, buf, size); + return size; +} + +static int io_write_data_type(void *opaque, uint8_t *buf, int size, + enum AVIODataMarkerType type, int64_t time) +{ + char timebuf[30], content[5] = { 0 }; + const char *str; + switch (type) { + case AVIO_DATA_MARKER_HEADER: str = "header"; break; + case AVIO_DATA_MARKER_SYNC_POINT: str = "sync"; break; + case AVIO_DATA_MARKER_BOUNDARY_POINT: str = "boundary"; break; + case AVIO_DATA_MARKER_UNKNOWN: str = "unknown"; break; + case AVIO_DATA_MARKER_TRAILER: str = "trailer"; break; + default: str = "unknown"; break; + } + if (time == AV_NOPTS_VALUE) + snprintf(timebuf, sizeof(timebuf), "nopts"); + else + snprintf(timebuf, sizeof(timebuf), "%"PRId64, time); + // There can be multiple header/trailer callbacks, only log the box type + // for header at out_size == 0 + if (type != AVIO_DATA_MARKER_UNKNOWN && + type != AVIO_DATA_MARKER_TRAILER && + (type != AVIO_DATA_MARKER_HEADER || out_size == 0) && + size >= 8) + memcpy(content, &buf[4], 4); + else + snprintf(content, sizeof(content), "-"); + printf("write_data len %d, time %s, type %s atom %s\n", size, timebuf, str, content); + return io_write(opaque, buf, size); +} + +static void init_out(const char *name) +{ + char buf[100]; + cur_name = name; + snprintf(buf, sizeof(buf), "%s.%s", cur_name, format); + + av_md5_init(md5); + out_size = 0; +} + +static void close_out(void) +{ + int i; + av_md5_final(md5, hash); + for (i = 0; i < HASH_SIZE; i++) + printf("%02x", hash[i]); + printf(" %d %s\n", out_size, cur_name); +} + +static void init_fps(int bf, int audio_preroll, int fps) +{ + AVStream *st; + int iobuf_size = force_iobuf_size ? force_iobuf_size : sizeof(iobuf); + ctx = avformat_alloc_context(); + if (!ctx) + exit(1); + ctx->oformat = av_guess_format(format, NULL, NULL); + if (!ctx->oformat) + exit(1); + ctx->pb = avio_alloc_context(iobuf, iobuf_size, AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL); + if (!ctx->pb) + exit(1); + ctx->pb->write_data_type = io_write_data_type; + ctx->flags |= AVFMT_FLAG_BITEXACT; + + st = avformat_new_stream(ctx, NULL); + if (!st) + exit(1); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_AAC; + st->codecpar->sample_rate = 44100; + st->codecpar->channels = 2; + st->time_base.num = 1; + st->time_base.den = 44100; + st->codecpar->extradata_size = sizeof(aac_extradata); + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + exit(1); + memcpy(st->codecpar->extradata, aac_extradata, sizeof(aac_extradata)); + audio_st = st; + + if (avformat_write_header(ctx, &opts) < 0) + exit(1); + av_dict_free(&opts); + + audio_duration = 1024LL * audio_st->time_base.den / audio_st->codecpar->sample_rate; + if (audio_preroll) + audio_preroll = 2048LL * audio_st->time_base.den / audio_st->codecpar->sample_rate; + + audio_dts = -audio_preroll; +} + +static void init(int bf, int audio_preroll) +{ + init_fps(bf, audio_preroll, 30); +} + +static void finish(void) +{ + av_write_trailer(ctx); + avio_context_free(&ctx->pb); + avformat_free_context(ctx); + ctx = NULL; +} + +static void pmt_cb(const uint8_t *p, int p_size) +{ + int pid, desc_list_len; + const uint8_t *desc_list_end; + const uint8_t *p_end = p + p_size - 4; + parse_section_header(&p, p_end); + + for (;;) { + int stream_type = get8(&p, p_end); + if (stream_type < 0) + break; + pid = get16(&p, p_end); + if (pid < 0) + break; + desc_list_len = get16(&p, p_end); + desc_list_len &= 0xfff; + desc_list_end = p + desc_list_len; + if (desc_list_end > p_end) + break; + for (;;) { + if (ff_parse_mpeg2_descriptor(ctx, audio_st, 0, &p, desc_list_end, NULL, 0, 0, NULL)) + break; + } + p = desc_list_end; + } + printf("disposition:%d\n", audio_st->disposition); +} + +int main(int argc, char **argv) +{ + md5 = av_md5_alloc(); + if (!md5) + return 1; + + // Test + init_out("pmt with editorial_classification"); + av_dict_set(&opts, "movflags", "frag_keyframe", 0); + init(0, 0); + pmt_cb(pmt_editorial_classification, sizeof(pmt_editorial_classification)); + finish(); + close_out(); + + av_free(md5); + + return 0; +} diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak index cf1ba18..622f199 100644 --- a/tests/fate/libavformat.mak +++ b/tests/fate/libavformat.mak @@ -22,6 +22,10 @@ FATE_LIBAVFORMAT-$(CONFIG_MOV_MUXER) += fate-movenc fate-movenc: libavformat/tests/movenc$(EXESUF) fate-movenc: CMD = run libavformat/tests/movenc +FATE_LIBAVFORMAT-yes += fate-descriptor +fate-descriptor: libavformat/tests/descriptor$(EXESUF) +fate-descriptor: CMD = run libavformat/tests/descriptor + FATE_LIBAVFORMAT += $(FATE_LIBAVFORMAT-yes) FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT) fate-libavformat: $(FATE_LIBAVFORMAT) diff --git a/tests/ref/fate/descriptor b/tests/ref/fate/descriptor new file mode 100644 index 0000000..23b6f18 --- /dev/null +++ b/tests/ref/fate/descriptor @@ -0,0 +1,5 @@ +write_data len 32, time nopts, type header atom ftyp +disposition:131328 +write_data len 649, time nopts, type header atom - +write_data len 24, time nopts, type trailer atom - +1da78d265861b40de21f6ec205d48ea4 705 pmt with editorial_classification -- 2.8.3
From fc2e281eb0e0e526fee52944205d6bb3729a17f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Krzciuk?= <lkrzc...@vewd.com> Date: Fri, 13 Apr 2018 14:57:57 +0200 Subject: [PATCH] avformat/mpegts: set AV_DISPOSITION_DESCRIPTIONS for OIPF cases 1. an audio component with an ISO_639_language_descriptor in the PMT with the audio_type field set to 0x03 2. a supplementary_audio_descriptor with the editorial_classification field set to 0x01 3. an ac-3_descriptor or an enhanced_ac-3_descriptor with a component_type field with the service_type flags set to Visually Impaired --- libavformat/mpegts.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 37a6aa8..629631f 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1835,6 +1835,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type break; case 0x03: st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; break; } } @@ -1910,6 +1911,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type switch ((flags >> 2) & 0x1F) { /* editorial_classification */ case 0x01: st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; break; case 0x02: st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; @@ -1934,6 +1936,34 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } } break; + case 0x6a: /* ac-3_descriptor */ + { + int component_type_flag = get8(pp, desc_end) & (1 << 7); + if (component_type_flag) { + int component_type = get8(pp, desc_end); + int service_type_mask = 0x38; // 0b00111000 + int service_type = ((component_type & service_type_mask) >> 3); + if (service_type == 0x02 /* 0b010 */) { + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; + av_log(ts->stream, AV_LOG_DEBUG, "New track disposition for id %u: %u\n", st->id, st->disposition); + } + } + } + break; + case 0x7a: /* enhanced_ac-3_descriptor */ + { + int component_type_flag = get8(pp, desc_end) & (1 << 7); + if (component_type_flag) { + int component_type = get8(pp, desc_end); + int service_type_mask = 0x38; // 0b00111000 + int service_type = ((component_type & service_type_mask) >> 3); + if (service_type == 0x02 /* 0b010 */) { + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; + av_log(ts->stream, AV_LOG_DEBUG, "New track disposition for id %u: %u\n", st->id, st->disposition); + } + } + } + break; default: break; } -- 2.8.3
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel