From patchwork Sat Jan 14 15:45:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Martinez X-Patchwork-Id: 40001 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bb05:b0:b6:a58c:cef with SMTP id fc5csp442610pzb; Sat, 14 Jan 2023 07:45:47 -0800 (PST) X-Google-Smtp-Source: AMrXdXv8eBshLy3i2nue3JgDGSB3FttSc0R2mroc6xFrFl4HhZLvjKjIsFmLWmfS8AVKH8YM2qkA X-Received: by 2002:aa7:c9c7:0:b0:499:cc32:6a52 with SMTP id i7-20020aa7c9c7000000b00499cc326a52mr3274674edt.16.1673711147497; Sat, 14 Jan 2023 07:45:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1673711147; cv=none; d=google.com; s=arc-20160816; b=IQ28xRIcGARpmufn/kUjyfVZb27ijwNarz9G9YvpAEcP3vpanuaVS6VaBxkGFIr90i prtz8ygCiCVaKO07Cm0CcQ0Rqi4xrX7kDDPXOtsA/lHy6eTe+YeF2CIF/b2ImDg+Bauo CHN09mWAYxHnbNfH4OplpvC2PpM77oC0+EG8X5w2lRSw1YfIuTjSw6GUQT79rXTAHf5e 8QzTwN+BHxUvqp2SGToFiYeiEyWNYy67Z1LPs3svvCJME5R1efWcPgluybppEDfXRqyv EvWHgj9Gc8UP9aKq/rj34/uD0CUtrKwhBZOxjMMagyCe6FBebeAs5wD0RVZvlN6QFf17 Hb/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:to:from :content-language:user-agent:mime-version:date:message-id :delivered-to; bh=LXeuG28Og67mmNbq9S3CRFkZJ3yy5Fj7bW+mjUdMzWE=; b=073RWC0Ue+g5YDUjLCfobZpFVtyVnC7NG3X19TMbiEarBEJtC7dxCdb0EfkKvWmprk 4WrieUJDzq7MLi5oi7wdA6UBTBZxN1rsRE8ZCVv924nOt8T8x5T/JWRKHEZYLzUiviCz 1CpnFd1oOcH+CTbXP2l/knBiHC5ZUbwbCIQhVpYSSNJzL05CzTtXNKHHmcotU97sIne4 JiRVdwTOkwN13mVF63xZptkpQXKivpImfY9sznndJWPl6D4XJHrVD7nOR1azKLH5l4ZH RfzZR/tLvvauGX0ohLsAL2zI/ZxxheL7HY4DTCLQNwm6ctKu8DUBUA6f703sfnElwuFR h05g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediaarea.net Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g12-20020a056402320c00b004615937b174si4081860eda.480.2023.01.14.07.45.46; Sat, 14 Jan 2023 07:45:47 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediaarea.net Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AF7A068B8BF; Sat, 14 Jan 2023 17:45:42 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from 3.mo550.mail-out.ovh.net (3.mo550.mail-out.ovh.net [46.105.60.232]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CF9F468B0E9 for ; Sat, 14 Jan 2023 17:45:35 +0200 (EET) Received: from director11.ghost.mail-out.ovh.net (unknown [10.108.1.162]) by mo550.mail-out.ovh.net (Postfix) with ESMTP id C5EAD22A9A for ; Sat, 14 Jan 2023 15:45:34 +0000 (UTC) Received: from ghost-submission-6684bf9d7b-24qnz (unknown [10.110.171.191]) by director11.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 407161FEC3 for ; Sat, 14 Jan 2023 15:45:34 +0000 (UTC) Received: from mediaarea.net ([37.59.142.102]) by ghost-submission-6684bf9d7b-24qnz with ESMTPSA id StvlCR7OwmPOOgAA547Lbg (envelope-from ) for ; Sat, 14 Jan 2023 15:45:34 +0000 Authentication-Results: garm.ovh; auth=pass (GARM-102R004f13e22cc-eb0e-40d0-8d71-cfe182269ebc, 531310C571D3E7C8BE5E63E303B7EE8DB87128E6) smtp.auth=jerome@mediaarea.net X-OVh-ClientIp: 84.143.156.21 Message-ID: Date: Sat, 14 Jan 2023 16:45:33 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Content-Language: en-US From: Jerome Martinez To: FFmpeg development discussions and patches X-Ovh-Tracer-Id: 14852308621273041145 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -110 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvhedruddttddgkedtucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecuhedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnegfrhhlucfvnfffucdlqddutddmnecujfgurheptgfkffggfgfhuffvsehmtderredtfeejnecuhfhrohhmpeflvghrohhmvgcuofgrrhhtihhnvgiiuceojhgvrhhomhgvsehmvgguihgrrghrvggrrdhnvghtqeenucggtffrrghtthgvrhhnpedtkefghffhvdeukeeggeetvefgteelkeeftdelvdeitddutdduffeivefhvdeuffenucffohhmrghinhepughighhithhiiigrthhiohhnghhuihguvghlihhnvghsrdhgohhvnecukfhppeduvdejrddtrddtrddupdefjedrheelrddugedvrddutddvnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepuddvjedrtddrtddruddpmhgrihhlfhhrohhmpeeojhgvrhhomhgvsehmvgguihgrrghrvggrrdhnvghtqedpnhgspghrtghpthhtohepuddprhgtphhtthhopehffhhmphgvghdquggvvhgvlhesfhhfmhhpvghgrdhorhhgpdfovfetjfhoshhtpehmohehhedtpdhmohguvgepshhmthhpohhuth Subject: [FFmpeg-devel] avformat/mxfenc: SMPTE RDD 48:2018 Amd 1:2022 (FFV1 in MXF) support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: suh5jjlHNZCk The arbitrary short element codes are the ones used by another muxer ( files available at https://www.digitizationguidelines.gov/guidelines/MXF_app_sampleFiles.html#2022 ) The support of RGBA descriptor is added, mainly by disabling in the CDCI descriptor related code the elements not in the Generic picture descriptor, and could be in a separated dedicated patch (move of Generic picture descriptor code in a dedicated function?). Tested with: ffmpeg -f lavfi -i testsrc=duration=10:size=ntsc:rate=ntsc -field_order bb -c:v ffv1 -level 0 test_ffv1_ntsc.mxf ffmpeg -f lavfi -i testsrc=duration=10:size=pal:rate=pal -field_order tt -c:v ffv1 -level 3 test_ffv1_pal.mxf ffmpeg -f lavfi -i testsrc=duration=10:size=1920x1080 -pix_fmt yuv422p10 -c:v ffv1 -level 3 test_ffv1_hd.mxf From 2e38dc0a114a1706f6d108ea9ca3e86083bfc2eb Mon Sep 17 00:00:00 2001 From: Jerome Martinez Date: Wed, 4 Jan 2023 13:56:21 +0100 Subject: [PATCH] avformat/mxfenc: SMPTE RDD 48:2018 Amd 1:2022 support --- libavformat/Makefile | 3 +- libavformat/mxfenc.c | 163 ++++++++++++++++++++++++++++++++++++++++++- libavformat/rangecoder_dec.c | 1 + 3 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 libavformat/rangecoder_dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index fa71ec12f7..3f80acbed9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -707,7 +707,8 @@ SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o -SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o \ + rangecoder_dec.o SHLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 58c551c83c..206b3484aa 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -51,6 +51,7 @@ #include "libavcodec/golomb.h" #include "libavcodec/h264.h" #include "libavcodec/packet_internal.h" +#include "libavcodec/rangecoder.h" #include "libavcodec/startcode.h" #include "avformat.h" #include "avio_internal.h" @@ -99,6 +100,7 @@ typedef struct MXFStreamContext { int b_picture_count; ///< maximum number of consecutive b pictures, used in mpeg-2 descriptor int low_delay; ///< low delay, used in mpeg-2 descriptor int avc_intra; + int micro_version; ///< format micro_version, used in ffv1 descriptor } MXFStreamContext; typedef struct MXFContainerEssenceEntry { @@ -127,6 +129,7 @@ enum ULIndex { INDEX_H264, INDEX_S436M, INDEX_PRORES, + INDEX_FFV1, }; static const struct { @@ -141,6 +144,7 @@ static const struct { { AV_CODEC_ID_JPEG2000, INDEX_JPEG2000 }, { AV_CODEC_ID_H264, INDEX_H264 }, { AV_CODEC_ID_PRORES, INDEX_PRORES }, + { AV_CODEC_ID_FFV1, INDEX_FFV1 }, { AV_CODEC_ID_NONE } }; @@ -148,6 +152,7 @@ static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st); static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st); static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st); static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st); +static void mxf_write_ffv1_desc(AVFormatContext *s, AVStream *st); static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st); static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st); static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st); @@ -205,6 +210,11 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x17,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x03,0x00 }, mxf_write_cdci_desc }, + // FFV1 + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x23,0x01,0x00 }, + { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x1d,0x00 }, + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x09,0x00,0x00 }, + mxf_write_ffv1_desc }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, @@ -229,6 +239,15 @@ static const UID mxf_d10_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 }, // D-10 525/50 NTSC 30mb/s }; + +static const UID mxf_ffv1_codec_uls[] = { + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x01,0x00 }, // FFV1 version 0 + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x02,0x00 }, // FFV1 version 1 + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x03,0x00 }, // FFV1 version 2 (was only experimental) + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x04,0x00 }, // FFV1 version 3 + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x05,0x00 }, // FFV1 version 4 +}; + static const uint8_t product_uid[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd,0x00,0x0c,0x00,0x02}; static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff }; static const uint8_t umid_ul[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 }; @@ -387,6 +406,10 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = { { 0x8302, FF_MXF_MasteringDisplayWhitePointChromaticity }, { 0x8303, FF_MXF_MasteringDisplayMaximumLuminance }, { 0x8304, FF_MXF_MasteringDisplayMinimumLuminance }, + // FFV1 + { 0xDFD9, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x06,0x00,0x00,0x00}}, /* FFV1 Micro-version */ + { 0xDFDA, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x05,0x00,0x00,0x00}}, /* FFV1 Version */ + { 0xDFDB, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x01,0x00,0x00,0x00}}, /* FFV1 Initialization Metadata */ }; #define MXF_NUM_TAGS FF_ARRAY_ELEMS(mxf_local_tag_batch) @@ -523,7 +546,7 @@ static void mxf_write_primer_pack(AVFormatContext *s) MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; int local_tag_number = MXF_NUM_TAGS, i; - int will_have_avc_tags = 0, will_have_mastering_tags = 0; + int will_have_avc_tags = 0, will_have_mastering_tags = 0, will_have_ffv1_tags = 0; for (i = 0; i < s->nb_streams; i++) { MXFStreamContext *sc = s->streams[i]->priv_data; @@ -533,6 +556,9 @@ static void mxf_write_primer_pack(AVFormatContext *s) if (av_stream_get_side_data(s->streams[i], AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL)) { will_have_mastering_tags = 1; } + if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_FFV1) { + will_have_ffv1_tags = 1; + } } if (!mxf->store_user_comments) { @@ -541,8 +567,11 @@ static void mxf_write_primer_pack(AVFormatContext *s) mxf_mark_tag_unused(mxf, 0x5003); } - if (!will_have_avc_tags) { + if (!will_have_avc_tags && !will_have_ffv1_tags) { mxf_mark_tag_unused(mxf, 0x8100); + } + + if (!will_have_avc_tags) { mxf_mark_tag_unused(mxf, 0x8200); mxf_mark_tag_unused(mxf, 0x8201); mxf_mark_tag_unused(mxf, 0x8202); @@ -555,6 +584,12 @@ static void mxf_write_primer_pack(AVFormatContext *s) mxf_mark_tag_unused(mxf, 0x8304); } + if (!will_have_ffv1_tags) { + mxf_mark_tag_unused(mxf, 0xDFD9); + mxf_mark_tag_unused(mxf, 0xDFDA); + mxf_mark_tag_unused(mxf, 0xDFDB); + } + for (i = 0; i < MXF_NUM_TAGS; i++) { if (mxf->unused_tags[i]) { local_tag_number--; @@ -1091,9 +1126,11 @@ static const UID mxf_mpegvideo_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53, static const UID mxf_wav_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }; static const UID mxf_aes3_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }; static const UID mxf_cdci_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }; +static const UID mxf_rgba_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }; static const UID mxf_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }; static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 }; +static const UID mxf_ffv1_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x03 }; static inline uint16_t rescale_mastering_chroma(AVRational q) { @@ -1195,6 +1232,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID avio_wb32(pb, -((st->codecpar->height - display_height)&1)); } + if (key != mxf_rgba_descriptor_key) { // component depth mxf_write_local_tag(s, 4, 0x3301); avio_wb32(pb, sc->component_depth); @@ -1231,6 +1269,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_local_tag(s, 4, 0x3306); avio_wb32(pb, color); } + } // if (key != mxf_rgba_descriptor_key) if (sc->signal_standard) { mxf_write_local_tag(s, 1, 0x3215); @@ -1326,6 +1365,13 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_uuid(pb, AVCSubDescriptor, 0); } + if (st->codecpar->codec_id == AV_CODEC_ID_FFV1) { + // write ffv1 sub descriptor ref + mxf_write_local_tag(s, 8 + 16, 0x8100); + mxf_write_refs_count(pb, 1); + mxf_write_uuid(pb, FFV1SubDescriptor, 0); + } + return pos; } @@ -1384,6 +1430,47 @@ static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st) } } +static void mxf_write_ffv1_subdesc(AVFormatContext *s, AVStream *st) +{ + AVIOContext *pb = s->pb; + MXFStreamContext *sc = st->priv_data; + int64_t pos; + + avio_write(pb, mxf_ffv1_subdescriptor_key, 16); + klv_encode_ber4_length(pb, 0); + pos = avio_tell(pb); + + mxf_write_local_tag(s, 16, 0x3C0A); + mxf_write_uuid(pb, FFV1SubDescriptor, 0); + + if (st->codecpar->extradata_size) { + mxf_write_local_tag(s, st->codecpar->extradata_size, 0xDFDB); + avio_write(pb, st->codecpar->extradata, st->codecpar->extradata_size); // FFV1InitializationMetadata + } + + mxf_write_local_tag(s, 2, 0xDFDA); + avio_wb16(pb, (*sc->codec_ul)[14]); // FFV1Version + + if (st->codecpar->extradata_size) { + mxf_write_local_tag(s, 2, 0xDFD9); + avio_wb16(pb, sc->micro_version); // FFV1MicroVersion + } + + mxf_update_klv_size(s->pb, pos); +} + +static void mxf_write_ffv1_desc(AVFormatContext *s, AVStream *st) +{ + int is_rgb, pos; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codecpar->format); + av_assert0(desc); + is_rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; + + pos = mxf_write_cdci_common(s, st, is_rgb ? mxf_rgba_descriptor_key : mxf_cdci_descriptor_key); + mxf_update_klv_size(s->pb, pos); + mxf_write_ffv1_subdesc(s, st); +} + static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st) { int64_t pos = mxf_write_generic_desc(s, st, mxf_s436m_anc_descriptor_key); @@ -2344,6 +2431,73 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, return 1; } +static inline int get_ffv1_unsigned_symbol(RangeCoder *c, uint8_t *state) { + if(get_rac(c, state+0)) + return 0; + else{ + int i, e; + unsigned a; + e= 0; + while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10 + e++; + if (e > 31) + return AVERROR_INVALIDDATA; + } + + a= 1; + for(i=e-1; i>=0; i--){ + a += a + get_rac(c, state+22 + FFMIN(i,9)); //22..31 + } + + return a; + } +} +#define FFV1_CONTEXT_SIZE 32 +static int mxf_parse_ffv1_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) +{ + MXFContext *mxf = s->priv_data; + MXFStreamContext *sc = st->priv_data; + uint8_t state[FFV1_CONTEXT_SIZE]; + RangeCoder c; + unsigned v; + + sc->frame_size = pkt->size; + + if (mxf->header_written) + return 1; + + memset(state, 128, sizeof(state)); + if (st->codecpar->extradata) { + ff_init_range_decoder(&c, st->codecpar->extradata, st->codecpar->extradata_size); + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8); + v = get_ffv1_unsigned_symbol(&c, state); + av_assert0(v >= 2); + if (v > 4) { + return 0; + } + sc->micro_version = get_ffv1_unsigned_symbol(&c, state); + } else { + uint8_t keystate = 128; + ff_init_range_decoder(&c, pkt->data, pkt->size); + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8); + get_rac(&c, &keystate); // keyframe + v = get_ffv1_unsigned_symbol(&c, state); + av_assert0(v < 2); + } + sc->codec_ul = &mxf_ffv1_codec_uls[v]; + + if (st->codecpar->field_order > AV_FIELD_PROGRESSIVE) { + sc->interlaced = 1; + sc->field_dominance = st->codecpar->field_order == (st->codecpar->field_order == AV_FIELD_TT || st->codecpar->field_order == AV_FIELD_TB) ? 1 : 2; + } + sc->aspect_ratio.num = st->codecpar->width * st->codecpar->sample_aspect_ratio.num; + sc->aspect_ratio.den = st->codecpar->height * st->codecpar->sample_aspect_ratio.den; + av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, + sc->aspect_ratio.num, sc->aspect_ratio.den, INT_MAX); + + return 1; +} + static const UID mxf_mpeg2_codec_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP @@ -2955,6 +3109,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "could not get h264 profile\n"); return -1; } + } else if (st->codecpar->codec_id == AV_CODEC_ID_FFV1) { + if (!mxf_parse_ffv1_frame(s, st, pkt)) { + av_log(s, AV_LOG_ERROR, "could not get ffv1 version\n"); + return -1; + } } if (mxf->cbr_index) { diff --git a/libavformat/rangecoder_dec.c b/libavformat/rangecoder_dec.c new file mode 100644 index 0000000000..7b727f656e --- /dev/null +++ b/libavformat/rangecoder_dec.c @@ -0,0 +1 @@ +#include "libavcodec/rangecoder.c"