From 620b1e7e989e71825858c621fa96a7e0a742d239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 11 Apr 2012 10:33:43 +0300 Subject: [PATCH 01/16] mem: Don't abort on av_malloc(0) in debug mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the behaviour consistent between debug and release mode. Signed-off-by: Martin Storsjö --- libavutil/mem.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavutil/mem.c b/libavutil/mem.c index 0fe9f5422a..3769da7d21 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -68,8 +68,6 @@ void *av_malloc(size_t size) long diff; #endif - assert(size); - /* let's disallow possible ambiguous cases */ if (size > (INT_MAX-32) || !size) return NULL; From f80ddd5bf760e685f4d912ce6e6763e6cab45910 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 9 Jul 2012 02:21:25 +0200 Subject: [PATCH 02/16] lavu: use intrinsics for emms on systems lacking inline asm support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Diego Biurrun Signed-off-by: Martin Storsjö --- configure | 3 +++ libavutil/internal.h | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 7507f8f387..a1506c9262 100755 --- a/configure +++ b/configure @@ -1116,6 +1116,7 @@ HAVE_LIST=" MapViewOfFile memalign mkstemp + mm_empty mmap nanosleep netinet_sctp_h @@ -2743,6 +2744,8 @@ elif enabled x86; then check_code ld intrin.h "__rdtsc()" && enable rdtsc + check_code ld mmintrin.h "_mm_empty()" && enable mm_empty + enable local_aligned_8 local_aligned_16 # check whether EBP is available on x86 diff --git a/libavutil/internal.h b/libavutil/internal.h index 41e8a9ab36..e8bcca571b 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -231,7 +231,7 @@ struct AVDictionary { # define ONLY_IF_THREADS_ENABLED(x) NULL #endif -#if HAVE_MMX +#if HAVE_MMX && HAVE_INLINE_ASM /** * Empty mmx state. * this must be called between any dsp function and float/double code. @@ -241,8 +241,11 @@ static av_always_inline void emms_c(void) { __asm__ volatile ("emms" ::: "memory"); } +#elif HAVE_MMX && HAVE_MM_EMPTY +# include +# define emms_c _mm_empty #else /* HAVE_MMX */ -#define emms_c() +# define emms_c() #endif /* HAVE_MMX */ #endif /* AVUTIL_INTERNAL_H */ From 3f150ffba31e404ca48624dc6af27b85c1704862 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 9 Jul 2012 02:21:26 +0200 Subject: [PATCH 03/16] x86/cpu: implement support for xgetbv through intrinsics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- configure | 2 ++ libavutil/x86/cpu.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/configure b/configure index a1506c9262..76ad4c7b70 100755 --- a/configure +++ b/configure @@ -1169,6 +1169,7 @@ HAVE_LIST=" windows_h winsock2_h xform_asm + xgetbv xmm_clobbers yasm " @@ -2742,6 +2743,7 @@ elif enabled sparc; then elif enabled x86; then + check_code ld immintrin.h "__xgetbv(0)" && enable xgetbv check_code ld intrin.h "__rdtsc()" && enable rdtsc check_code ld mmintrin.h "_mm_empty()" && enable mm_empty diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 5d77b0c2df..dfdc12394c 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -34,8 +34,19 @@ : "=a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx) \ : "0" (index)) +#if HAVE_INLINE_ASM #define xgetbv(index, eax, edx) \ __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c" (index)) +#elif HAVE_XGETBV +#include + +#define xgetbv(index, eax, edx) \ + do { \ + uint64_t res = __xgetbv(index); \ + eax = res; \ + edx = res >> 32; \ + } while (0) +#endif /* HAVE_XGETBV */ #define get_eflags(x) \ __asm__ volatile ("pushfl \n" \ From c0ee695bd7b278f83252c9f93803b107d7aa1e9a Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 9 Jul 2012 02:21:27 +0200 Subject: [PATCH 04/16] x86/cpu: implement support for cpuid through intrinsics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- configure | 2 ++ libavutil/x86/cpu.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/configure b/configure index 76ad4c7b70..0f51523ac6 100755 --- a/configure +++ b/configure @@ -1061,6 +1061,7 @@ HAVE_LIST=" cbrtf closesocket cmov + cpuid dcbzl dev_bktr_ioctl_bt848_h dev_bktr_ioctl_meteor_h @@ -2744,6 +2745,7 @@ elif enabled sparc; then elif enabled x86; then check_code ld immintrin.h "__xgetbv(0)" && enable xgetbv + check_code ld intrin.h "int info[4]; __cpuid(info, 0)" && enable cpuid check_code ld intrin.h "__rdtsc()" && enable rdtsc check_code ld mmintrin.h "_mm_empty()" && enable mm_empty diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index dfdc12394c..7d65c6075e 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -25,6 +25,7 @@ #include "libavutil/x86_cpu.h" #include "libavutil/cpu.h" +#if HAVE_INLINE_ASM /* ebx saving is necessary for PIC. gcc seems unable to see it alone */ #define cpuid(index, eax, ebx, ecx, edx) \ __asm__ volatile ( \ @@ -33,6 +34,19 @@ "xchg %%"REG_b", %%"REG_S \ : "=a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx) \ : "0" (index)) +#elif HAVE_CPUID +#include + +#define cpuid(index, eax, ebx, ecx, edx) \ + do { \ + int info[4]; \ + __cpuid(info, index); \ + eax = info[0]; \ + ebx = info[1]; \ + ecx = info[2]; \ + edx = info[3]; \ + } while (0) +#endif /* HAVE_CPUID */ #if HAVE_INLINE_ASM #define xgetbv(index, eax, edx) \ From 358d854df80e035c9d47bae21492b51b406dbe68 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 9 Jul 2012 02:21:28 +0200 Subject: [PATCH 05/16] x86/cpu: implement get/set_eflags using intrinsics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Diego Biurrun Signed-off-by: Martin Storsjö --- configure | 2 ++ libavutil/x86/cpu.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/configure b/configure index 0f51523ac6..ffb1e7e667 100755 --- a/configure +++ b/configure @@ -1126,6 +1126,7 @@ HAVE_LIST=" rdtsc round roundf + rweflags sched_getaffinity sdl sdl_video_size @@ -2747,6 +2748,7 @@ elif enabled x86; then check_code ld immintrin.h "__xgetbv(0)" && enable xgetbv check_code ld intrin.h "int info[4]; __cpuid(info, 0)" && enable cpuid check_code ld intrin.h "__rdtsc()" && enable rdtsc + check_code ld intrin.h "unsigned int x = __readeflags()" && enable rweflags check_code ld mmintrin.h "_mm_empty()" && enable mm_empty diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 7d65c6075e..d3b1bd5ea6 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -62,6 +62,8 @@ } while (0) #endif /* HAVE_XGETBV */ +#if HAVE_INLINE_ASM + #define get_eflags(x) \ __asm__ volatile ("pushfl \n" \ "pop %0 \n" \ @@ -72,6 +74,18 @@ "popfl \n" \ :: "r"(x)) +#elif HAVE_RWEFLAGS + +#include + +#define get_eflags(x) \ + x = __readeflags() + +#define set_eflags(x) \ + __writeeflags(x) + +#endif /* HAVE_INLINE_ASM */ + /* Function to test if multimedia instructions are supported... */ int ff_get_cpu_flags_x86(void) { From 5255ca24cd1136175868fec3b419e3af024042a1 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Tue, 28 Feb 2012 14:16:36 +0000 Subject: [PATCH 06/16] mxfdec: set track edit rate num/den in expected order This matches the order used for the index table edit rate. Reviewed-by: Baptiste Coudurier Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 594ba49f34..70f99412e4 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -631,8 +631,8 @@ static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid avio_read(pb, track->track_number, 4); break; case 0x4B01: - track->edit_rate.den = avio_rb32(pb); track->edit_rate.num = avio_rb32(pb); + track->edit_rate.den = avio_rb32(pb); break; case 0x4803: avio_read(pb, track->sequence_ref, 16); @@ -1369,7 +1369,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) if (st->duration == -1) st->duration = AV_NOPTS_VALUE; st->start_time = component->start_position; - avpriv_set_pts_info(st, 64, material_track->edit_rate.num, material_track->edit_rate.den); + avpriv_set_pts_info(st, 64, material_track->edit_rate.den, material_track->edit_rate.num); PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul); codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul); From dfefede00e3ea03f2a1bdfcb1b6db11699229049 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Tue, 28 Feb 2012 14:16:38 +0000 Subject: [PATCH 07/16] mxfdec: detect uncomp pictures using essence container ul This supports detection of uncompressed picture in files that didn't include a Picture Coding Label. The lables weren't available until SMPTE 377-1 and RP224v10 Reviewed-by: Baptiste Coudurier Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 70f99412e4..31585d7516 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -892,6 +892,7 @@ static const MXFCodecUL mxf_picture_essence_container_uls[] = { // video essence container uls { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, CODEC_ID_DVVIDEO }, /* DV 625 25mbps */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, }; static const MXFCodecUL mxf_sound_essence_container_uls[] = { From fda891e108f53b1dd2d9801232c2893e45c072a1 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Tue, 28 Feb 2012 14:16:39 +0000 Subject: [PATCH 08/16] mxfdec: set pixel format for cdci picture formats The properties of the CDCI Descriptor are insufficient to specify the pixel format for uncompressed picture data. SMPTE 377-1 and RP224v10 have defined a set of picture coding labels to indicate what formatting was used. This patch uses 2 labels to detect UYVY422 or YUYV422 pixel formats. It defaults to UYVY422 for 8-bit 4:2:2 pictures to support files that were created before the coding labels were introduced ~2008 The codec pix_fmt default was changed from 0 (PIX_FMT_YUV420P) to -1 (PIX_FMT_NONE) Reviewed-by: Baptiste Coudurier Signed-off-by: Michael Niedermayer --- libavformat/mxf.c | 6 ++++++ libavformat/mxf.h | 1 + libavformat/mxfdec.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/libavformat/mxf.c b/libavformat/mxf.c index e4d9fbd542..77f0b58113 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -55,6 +55,12 @@ const MXFCodecUL ff_mxf_codec_uls[] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, }; +const MXFCodecUL ff_mxf_pixel_format_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x01 }, 16, PIX_FMT_UYVY422 }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x02 }, 16, PIX_FMT_YUYV422 }, + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, PIX_FMT_NONE }, +}; + static const struct { enum PixelFormat pix_fmt; const char data[16]; diff --git a/libavformat/mxf.h b/libavformat/mxf.h index beb66281ab..8d3c0b9c55 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -60,6 +60,7 @@ typedef struct { extern const MXFCodecUL ff_mxf_data_definition_uls[]; extern const MXFCodecUL ff_mxf_codec_uls[]; +extern const MXFCodecUL ff_mxf_pixel_format_uls[]; int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum PixelFormat *pix_fmt); diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 31585d7516..f24e25f5bc 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -134,6 +134,9 @@ typedef struct { int height; int channels; int bits_per_sample; + unsigned int component_depth; + unsigned int horiz_subsampling; + unsigned int vert_subsampling; UID *sub_descriptors_refs; int sub_descriptors_count; int linked_track_id; @@ -789,6 +792,7 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFDescriptor *descriptor = arg; + descriptor->pix_fmt = PIX_FMT_NONE; switch(tag) { case 0x3F01: descriptor->sub_descriptors_count = avio_rb32(pb); @@ -819,6 +823,15 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int descriptor->aspect_ratio.num = avio_rb32(pb); descriptor->aspect_ratio.den = avio_rb32(pb); break; + case 0x3301: + descriptor->component_depth = avio_rb32(pb); + break; + case 0x3302: + descriptor->horiz_subsampling = avio_rb32(pb); + break; + case 0x3308: + descriptor->vert_subsampling = avio_rb32(pb); + break; case 0x3D03: descriptor->sample_rate.num = avio_rb32(pb); descriptor->sample_rate.den = avio_rb32(pb); @@ -1294,6 +1307,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) UID *essence_container_ul = NULL; const MXFCodecUL *codec_ul = NULL; const MXFCodecUL *container_ul = NULL; + const MXFCodecUL *pix_fmt_ul = NULL; AVStream *st; if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) { @@ -1427,8 +1441,23 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) st->codec->codec_id = container_ul->id; st->codec->width = descriptor->width; st->codec->height = descriptor->height; - if (st->codec->codec_id == CODEC_ID_RAWVIDEO) + if (st->codec->codec_id == CODEC_ID_RAWVIDEO) { st->codec->pix_fmt = descriptor->pix_fmt; + if (st->codec->pix_fmt == PIX_FMT_NONE) { + pix_fmt_ul = mxf_get_codec_ul(ff_mxf_pixel_format_uls, + &descriptor->essence_codec_ul); + st->codec->pix_fmt = pix_fmt_ul->id; + if (st->codec->pix_fmt == PIX_FMT_NONE) { + /* support files created before RP224v10 by defaulting to UYVY422 + if subsampling is 4:2:2 and component depth is 8-bit */ + if (descriptor->horiz_subsampling == 2 && + descriptor->vert_subsampling == 1 && + descriptor->component_depth == 8) { + st->codec->pix_fmt = PIX_FMT_UYVY422; + } + } + } + } st->need_parsing = AVSTREAM_PARSE_HEADERS; } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul); From 1fadf53e0073176966e52d9a8ffd78ffe85e2d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 2 Mar 2012 11:16:10 +0100 Subject: [PATCH 09/16] mxfdec: truncate packets that extend past the next edit unit This fixes rare cases where OPAtom may be treated as OP1a, causing all essence to be read into RAM. Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 65 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index f24e25f5bc..a0bbd7a335 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1877,48 +1877,53 @@ static int mxf_read_header(AVFormatContext *s) } /** - * Computes DTS and PTS for the given video packet based on its offset. + * Sets mxf->current_edit_unit based on what offset we're currently at. + * @return next_ofs if OK, <0 on error */ -static void mxf_packet_timestamps(MXFContext *mxf, AVPacket *pkt) +static int64_t mxf_set_current_edit_unit(MXFContext *mxf, int64_t current_offset) { - int64_t last_ofs = -1, next_ofs; + int64_t last_ofs = -1, next_ofs = -1; MXFIndexTable *t = &mxf->index_tables[0]; /* this is called from the OP1a demuxing logic, which means there * may be no index tables */ if (mxf->nb_index_tables <= 0) - return; + return -1; - /* find mxf->current_edit_unit so that the next edit unit starts ahead of pkt->pos */ + /* find mxf->current_edit_unit so that the next edit unit starts ahead + * of current_offset */ while (mxf->current_edit_unit >= 0) { - if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_ofs, 0) < 0) - break; + if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, + NULL, &next_ofs, 0) < 0) + return -1; if (next_ofs <= last_ofs) { /* large next_ofs didn't change or current_edit_unit wrapped * around this fixes the infinite loop on zzuf3.mxf */ av_log(mxf->fc, AV_LOG_ERROR, "next_ofs didn't change. not deriving packet timestamps\n"); - return; + return -1; } - if (next_ofs > pkt->pos) + if (next_ofs > current_offset) break; last_ofs = next_ofs; mxf->current_edit_unit++; } - if (mxf->current_edit_unit < 0 || mxf->current_edit_unit >= t->nb_ptses) - return; + /* not checking mxf->current_edit_unit >= t->nb_ptses here since CBR files + * may lack IndexEntryArrays */ + if (mxf->current_edit_unit < 0) + return -1; - pkt->dts = mxf->current_edit_unit + t->first_dts; - pkt->pts = t->ptses[mxf->current_edit_unit]; + return next_ofs; } static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) { KLVPacket klv; + MXFContext *mxf = s->priv_data; while (!s->pb->eof_reached) { if (klv_read_packet(&klv, s->pb) < 0) @@ -1936,12 +1941,30 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) if (IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) { int index = mxf_get_stream_index(s, &klv); + int64_t next_ofs, next_klv; + if (index < 0) { av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); goto skip; } if (s->streams[index]->discard == AVDISCARD_ALL) goto skip; + + next_klv = avio_tell(s->pb) + klv.length; + next_ofs = mxf_set_current_edit_unit(mxf, klv.offset); + + if (next_ofs >= 0 && next_klv > next_ofs) { + /* if this check is hit then it's possible OPAtom was treated + * as OP1a truncate the packet since it's probably very large + * (>2 GiB is common) */ + av_log_ask_for_sample(s, + "KLV for edit unit %i extends into next " + "edit unit - OPAtom misinterpreted as " + "OP1a?\n", + mxf->current_edit_unit); + klv.length = next_ofs - avio_tell(s->pb); + } + /* check for 8 channels AES3 element */ if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) { if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) { @@ -1956,8 +1979,20 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = index; pkt->pos = klv.offset; - if (s->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) - mxf_packet_timestamps(s->priv_data, pkt); /* offset -> EditUnit -> DTS/PTS */ + if (s->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) { + /* mxf->current_edit_unit good - see if we have an + * index table to derive timestamps from */ + MXFIndexTable *t = &mxf->index_tables[0]; + + if (mxf->nb_index_tables >= 1 && + mxf->current_edit_unit < t->nb_ptses) { + pkt->dts = mxf->current_edit_unit + t->first_dts; + pkt->pts = t->ptses[mxf->current_edit_unit]; + } + } + + /* seek for truncated packets */ + avio_seek(s->pb, next_klv, SEEK_SET); return 0; } else From fb8fa3c67c78d2218c578164b756cd000b0736d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 2 Mar 2012 11:33:28 +0100 Subject: [PATCH 10/16] mxfdec: fix Avid AirSpeed files being misinterpreted as OP1a The "ECs != 1 -> OP1a" assumption was wrong. Luckily, the file that triggered that behavior had two ECs, not zero. Hence distinguishing between them is simple in this case. Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index a0bbd7a335..74a86a8814 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -510,16 +510,20 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size else if (op[12] == 64&& op[13] == 1) mxf->op = OPSonyOpt; else if (op[12] == 0x10) { /* SMPTE 390m: "There shall be exactly one essence container" - * 2011_DCPTEST_24FPS.V.mxf violates this and is frame wrapped, - * which is why we assume OP1a. */ + * The following block deals with files that violate this, namely: + * 2011_DCPTEST_24FPS.V.mxf - two ECs, OP1a + * abcdefghiv016f56415e.mxf - zero ECs, OPAtom, output by Avid AirSpeed */ if (nb_essence_containers != 1) { + MXFOP op = nb_essence_containers ? OP1a : OPAtom; + /* only nag once */ if (!mxf->op) av_log(mxf->fc, AV_LOG_WARNING, - "\"OPAtom\" with %u ECs - assuming OP1a\n", - nb_essence_containers); + "\"OPAtom\" with %u ECs - assuming %s\n", + nb_essence_containers, + op == OP1a ? "OP1a" : "OPAtom"); - mxf->op = OP1a; + mxf->op = op; } else mxf->op = OPAtom; } else { From 5ed032fb8b34d5655b606c20bcc238116f96e816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 7 Mar 2012 10:52:39 +0100 Subject: [PATCH 11/16] mxfdec: Add intra_only flag to MXFTrack This allows future assumptions to be made without affecting non-intra files. Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 74a86a8814..d73ad2ce46 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -121,6 +121,7 @@ typedef struct { int track_id; uint8_t track_number[4]; AVRational edit_rate; + int intra_only; } MXFTrack; typedef struct { @@ -912,6 +913,19 @@ static const MXFCodecUL mxf_picture_essence_container_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, }; + +/* EC ULs for intra-only formats */ +static const MXFCodecUL mxf_intra_only_essence_container_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 Mappings */ + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, +}; + +/* intra-only PictureEssenceCoding ULs, where no corresponding EC UL exists */ +static const MXFCodecUL mxf_intra_only_picture_essence_coding_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra Profiles */ + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, +}; + static const MXFCodecUL mxf_sound_essence_container_uls[] = { // sound essence container uls { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */ @@ -1284,6 +1298,14 @@ finish_decoding_index: return ret; } +static int mxf_is_intra_only(MXFDescriptor *d) +{ + return mxf_get_codec_ul(mxf_intra_only_essence_container_uls, + &d->essence_container_ul)->id != CODEC_ID_NONE || + mxf_get_codec_ul(mxf_intra_only_picture_essence_coding_uls, + &d->essence_codec_ul)->id != CODEC_ID_NONE; +} + static int mxf_parse_structural_metadata(MXFContext *mxf) { MXFPackage *material_package = NULL; @@ -1440,6 +1462,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) st->codec->extradata_size = descriptor->extradata_size; } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + source_track->intra_only = mxf_is_intra_only(descriptor); container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul); if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = container_ul->id; From 634d670538738212d3143368b772e7ae11543906 Mon Sep 17 00:00:00 2001 From: Joseph Artsimovich Date: Tue, 7 Feb 2012 10:48:43 +0000 Subject: [PATCH 12/16] mxfdec: fix frame height vs field height confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Reveiwed-by: Baptiste Coudurier Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxf.h | 8 ++++++++ libavformat/mxfdec.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/libavformat/mxf.h b/libavformat/mxf.h index 8d3c0b9c55..f39a013f7b 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -46,6 +46,14 @@ enum MXFMetadataSetType { TypeBottom,// add metadata type before this }; +enum MXFFrameLayout { + FullFrame = 0, + MixedFields, + OneField, + SegmentedFrame, + SeparateFields +}; + typedef struct { UID key; int64_t offset; diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index d73ad2ce46..d10d5aa18c 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -132,7 +132,8 @@ typedef struct { AVRational sample_rate; AVRational aspect_ratio; int width; - int height; + int height; /* Field height, not frame height */ + int frame_layout; /* See MXFFrameLayout enum */ int channels; int bits_per_sample; unsigned int component_depth; @@ -824,6 +825,9 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int case 0x3202: descriptor->height = avio_rb32(pb); break; + case 0x320C: + descriptor->frame_layout = avio_r8(pb); + break; case 0x320E: descriptor->aspect_ratio.num = avio_rb32(pb); descriptor->aspect_ratio.den = avio_rb32(pb); @@ -1467,7 +1471,34 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = container_ul->id; st->codec->width = descriptor->width; + /* Field height, not frame height */ st->codec->height = descriptor->height; + switch (descriptor->frame_layout) { + case SegmentedFrame: + /* This one is a weird layout I don't fully understand. */ + av_log(mxf->fc, AV_LOG_INFO, + "SegmentedFrame layout isn't currently supported\n"); + break; + case FullFrame: + break; + case OneField: + /* Every other line is stored and needs to be duplicated. */ + av_log(mxf->fc, AV_LOG_INFO, + "OneField frame layout isn't currently supported\n"); + break; + /* The correct thing to do here is fall through, but by + * breaking we might be able to decode some streams at half + * the vertical resolution, rather than not al all. + * It's also for compatibility with the old behavior. */ + case SeparateFields: + case MixedFields: + /* Turn field height into frame height. */ + st->codec->height *= 2; + default: + av_log(mxf->fc, AV_LOG_INFO, + "Unknown frame layout type: %d\n", + descriptor->frame_layout); + } if (st->codec->codec_id == CODEC_ID_RAWVIDEO) { st->codec->pix_fmt = descriptor->pix_fmt; if (st->codec->pix_fmt == PIX_FMT_NONE) { From 34ca5ae51d7d411a5a891521a79c1284e046bf2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 7 Mar 2012 10:03:16 +0100 Subject: [PATCH 13/16] mxfdec: let pkt->pts = mxf->current_edit_unit if intra-only We cannot do this in general since we could be reading a file with B-frames while lacking an index. Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index d10d5aa18c..43e5135e56 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -2000,11 +2000,17 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) { int index = mxf_get_stream_index(s, &klv); int64_t next_ofs, next_klv; + AVStream *st; + MXFTrack *track; if (index < 0) { av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); goto skip; } + + st = s->streams[index]; + track = st->priv_data; + if (s->streams[index]->discard == AVDISCARD_ALL) goto skip; @@ -2046,6 +2052,11 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) mxf->current_edit_unit < t->nb_ptses) { pkt->dts = mxf->current_edit_unit + t->first_dts; pkt->pts = t->ptses[mxf->current_edit_unit]; + } else if (track->intra_only) { + /* intra-only -> PTS = EditUnit. + * let utils.c figure out DTS since it can be + * < PTS if low_delay = 0 (Sony IMX30) */ + pkt->pts = mxf->current_edit_unit; } } From 83728d2d36721015fd000ed58216a73867281e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 20 Mar 2012 11:03:48 +0100 Subject: [PATCH 14/16] mxfdec: only parse next partition pack if parsing forward Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 43e5135e56..796a97f2fe 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1873,6 +1873,9 @@ static int mxf_read_header(AVFormatContext *s) /* next partition pack - keep going, seek to previous partition or stop */ if(mxf_parse_handle_partition_or_eof(mxf) <= 0) break; + else if (mxf->parsing_backward) + continue; + /* we're still parsing forward. proceed to parsing this partition pack */ } for (metadata = mxf_metadata_read_table; metadata->read; metadata++) { From f39bbc9d2130bfb2b383c70105a6d54e6cadbbb5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 26 Mar 2012 15:05:02 +0200 Subject: [PATCH 15/16] mxfdec: fix off by one error. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libavformat/mxfdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 796a97f2fe..a68b1a42ec 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1070,7 +1070,7 @@ static int mxf_edit_unit_absolute_offset(MXFContext *mxf, MXFIndexTable *index_t if (s->nb_index_entries == 2 * s->index_duration + 1) index *= 2; /* Avid index */ - if (index < 0 || index > s->nb_index_entries) { + if (index < 0 || index >= s->nb_index_entries) { av_log(mxf->fc, AV_LOG_ERROR, "IndexSID %i segment at %"PRId64" IndexEntryArray too small\n", index_table->index_sid, s->index_start_position); return AVERROR_INVALIDDATA; From ed219ed36606be307403b46f969a82bf0568865b Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 10 Jul 2012 13:38:56 +0200 Subject: [PATCH 16/16] mss1: fix decoding masked regions in interframes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spotted by Alberto Delmás --- libavcodec/mss1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c index 523a9616bf..6eb9f1486e 100644 --- a/libavcodec/mss1.c +++ b/libavcodec/mss1.c @@ -499,7 +499,7 @@ static int decode_region_masked(MSS1Context *ctx, ArithCoder *acoder, dst += x + y * stride; mask += x + y * mask_stride; - if (mask[0] != 0xFF) + if (mask[0] == 0xFF) dst[0] = decode_top_left_pixel(acoder, pctx); for (j = 0; j < height; j++) { for (i = 0; i < width; i++) {