mxfenc.c 129 KB
Newer Older
1 2 3
/*
 * MXF muxer
 * Copyright (c) 2008 GUCAS, Zhentan Feng <spyfeng at gmail dot com>
4
 * Copyright (c) 2008 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * 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
21 22 23
 */

/*
24
 * signal_standard, color_siting, store_user_comments, sample rate and klv_fill_key version
25
 * fixes sponsored by NOA GmbH
26 27 28 29 30 31 32 33
 */

/*
 * References
 * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value
 * SMPTE 377M MXF File Format Specifications
 * SMPTE 379M MXF Generic Container
 * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container
34
 * SMPTE 422M Mapping JPEG 2000 Codestreams into the MXF Generic Container
35 36 37 38
 * SMPTE RP210: SMPTE Metadata Dictionary
 * SMPTE RP224: Registry of SMPTE Universal Labels
 */

39
#include <inttypes.h>
40
#include <math.h>
41
#include <time.h>
42

43
#include "libavutil/opt.h"
44
#include "libavutil/random_seed.h"
45
#include "libavutil/timecode.h"
46
#include "libavutil/avassert.h"
47
#include "libavutil/pixdesc.h"
48
#include "libavutil/time_internal.h"
49
#include "libavcodec/bytestream.h"
50
#include "libavcodec/dnxhddata.h"
51
#include "libavcodec/dv_profile.h"
52 53
#include "libavcodec/h264_ps.h"
#include "libavcodec/golomb.h"
54
#include "libavcodec/internal.h"
55
#include "audiointerleave.h"
56
#include "avformat.h"
Paul B Mahol's avatar
Paul B Mahol committed
57
#include "avio_internal.h"
58
#include "internal.h"
59
#include "avc.h"
60
#include "mxf.h"
61
#include "config.h"
62

63
extern AVOutputFormat ff_mxf_d10_muxer;
64
extern AVOutputFormat ff_mxf_opatom_muxer;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
65

66
#define EDIT_UNITS_PER_BODY 250
67
#define KAG_SIZE 512
68

69
typedef struct MXFLocalTagPair {
70 71 72 73
    int local_tag;
    UID uid;
} MXFLocalTagPair;

74
typedef struct MXFIndexEntry {
75 76
    uint8_t flags;
    uint64_t offset;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
77
    unsigned slice_offset; ///< offset of audio slice
78
    uint16_t temporal_ref;
79 80
} MXFIndexEntry;

81
typedef struct MXFStreamContext {
82
    AudioInterleaveContext aic;
83
    UID track_essence_element_key;
84
    int index;               ///< index in mxf_essence_container_uls table
85
    const UID *codec_ul;
86
    int order;               ///< interleaving order if dts are equal
87
    int interlaced;          ///< whether picture is interlaced
88
    int field_dominance;     ///< tff=1, bff=2
89
    int component_depth;
90
    int color_siting;
91
    int signal_standard;
92
    int h_chroma_sub_sample;
93
    int v_chroma_sub_sample;
94
    int temporal_reordering;
95
    AVRational aspect_ratio; ///< display aspect ratio
96
    int closed_gop;          ///< gop is closed, used in mpeg-2 frame parsing
97
    int video_bit_rate;
98 99
    int slice_offset;
    int frame_size;          ///< frame size in bytes
100 101 102 103
    int seq_closed_gop;      ///< all gops in sequence are closed, used in mpeg-2 descriptor
    int max_gop;             ///< maximum gop size, used by mpeg-2 descriptor
    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
104
    int avc_intra;
105 106
} MXFStreamContext;

107
typedef struct MXFContainerEssenceEntry {
108 109
    UID container_ul;
    UID element_ul;
110
    UID codec_ul;
111
    void (*write_desc)(AVFormatContext *, AVStream *);
112
} MXFContainerEssenceEntry;
113

114 115 116 117
typedef struct MXFPackage {
    char *name;
    enum MXFMetadataSetType type;
    int instance;
118
    struct MXFPackage *ref;
119 120
} MXFPackage;

121
enum ULIndex {
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    INDEX_MPEG2 = 0,
    INDEX_AES3,
    INDEX_WAV,
    INDEX_D10_625_50_50_VIDEO,
    INDEX_D10_625_50_50_AUDIO,
    INDEX_D10_525_60_50_VIDEO,
    INDEX_D10_525_60_50_AUDIO,
    INDEX_D10_625_50_40_VIDEO,
    INDEX_D10_625_50_40_AUDIO,
    INDEX_D10_525_60_40_VIDEO,
    INDEX_D10_525_60_40_AUDIO,
    INDEX_D10_625_50_30_VIDEO,
    INDEX_D10_625_50_30_AUDIO,
    INDEX_D10_525_60_30_VIDEO,
    INDEX_D10_525_60_30_AUDIO,
    INDEX_DV,
    INDEX_DV25_525_60,
    INDEX_DV25_625_50,
140 141
    INDEX_DV25_525_60_IEC,
    INDEX_DV25_625_50_IEC,
142 143 144 145 146 147
    INDEX_DV50_525_60,
    INDEX_DV50_625_50,
    INDEX_DV100_1080_60,
    INDEX_DV100_1080_50,
    INDEX_DV100_720_60,
    INDEX_DV100_720_50,
148
    INDEX_DNXHD,
149 150
    INDEX_JPEG2000,
    INDEX_H264,
151
    INDEX_S436M,
152
    INDEX_PRORES,
153 154
};

155 156 157 158 159 160 161 162
static const struct {
    enum AVCodecID id;
    enum ULIndex index;
} mxf_essence_mappings[] = {
    { AV_CODEC_ID_MPEG2VIDEO, INDEX_MPEG2 },
    { AV_CODEC_ID_PCM_S24LE,  INDEX_AES3 },
    { AV_CODEC_ID_PCM_S16LE,  INDEX_AES3 },
    { AV_CODEC_ID_DVVIDEO,    INDEX_DV },
163
    { AV_CODEC_ID_DNXHD,      INDEX_DNXHD },
164 165
    { AV_CODEC_ID_JPEG2000,   INDEX_JPEG2000 },
    { AV_CODEC_ID_H264,       INDEX_H264 },
166
    { AV_CODEC_ID_PRORES,     INDEX_PRORES },
167 168 169 170 171 172
    { AV_CODEC_ID_NONE }
};

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);
173
static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st);
174 175
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
176
static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st);
177

178
static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
179
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 },
180
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
181
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
182
      mxf_write_mpegvideo_desc },
183 184 185
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x03,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x16,0x01,0x03,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
186
      mxf_write_aes3_desc },
187
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 },
188
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x16,0x01,0x01,0x00 },
189
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
190
      mxf_write_wav_desc },
Baptiste Coudurier's avatar
Baptiste Coudurier committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    // D-10 625/50 PAL 50mb/s
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 },
      mxf_write_cdci_desc },
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
      mxf_write_generic_sound_desc },
    // D-10 525/60 NTSC 50mb/s
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x02,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x02 },
      mxf_write_cdci_desc },
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x02,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
      mxf_write_generic_sound_desc },
    // D-10 625/50 PAL 40mb/s
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x03,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x03 },
      mxf_write_cdci_desc },
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x03,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
      mxf_write_generic_sound_desc },
    // D-10 525/60 NTSC 40mb/s
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x04,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x04 },
      mxf_write_cdci_desc },
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x04,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
      mxf_write_generic_sound_desc },
    // D-10 625/50 PAL 30mb/s
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 },
      mxf_write_cdci_desc },
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
      mxf_write_generic_sound_desc },
    // D-10 525/60 NTSC 30mb/s
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x06 },
      mxf_write_cdci_desc },
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
      mxf_write_generic_sound_desc },
245
    // DV Unknown
246 247 248 249
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x7F,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x00,0x00,0x00 },
      mxf_write_cdci_desc },
250

251 252 253 254 255 256 257 258 259 260
    // DV25 525/60
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x40,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x01,0x00 },
      mxf_write_cdci_desc },
    // DV25 625/50
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 },
      mxf_write_cdci_desc },
261 262 263 264 265 266 267 268 269 270 271 272 273

    // IEC DV25 525/60
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x01,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x01,0x00 },
      mxf_write_cdci_desc },
    // IEC DV25 625/50
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x02,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 },
      mxf_write_cdci_desc },

      // DV50 525/60
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x50,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x03,0x00 },
      mxf_write_cdci_desc },
    // DV50 625/50
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x51,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 },
      mxf_write_cdci_desc },
    // DV100 1080/60
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x60,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x05,0x00 },
      mxf_write_cdci_desc },
    // DV100 1080/50
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x61,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x06,0x00 },
      mxf_write_cdci_desc },
    // DV100 720/60
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x62,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x07,0x00 },
      mxf_write_cdci_desc },
    // DV100 720/50
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x63,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x08,0x00 },
      mxf_write_cdci_desc },
303
    // DNxHD
304 305
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
306
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 },
307
      mxf_write_cdci_desc },
308 309 310 311 312
    // JPEG2000
    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 },
      { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x08,0x00 },
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 },
      mxf_write_cdci_desc },
313 314 315 316
    // H.264
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x10,0x60,0x01 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
317
      mxf_write_h264_desc },
318 319 320 321 322
    // S436M ANC
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x17,0x01,0x02,0x00 },
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x01,0x5C,0x00 },
      mxf_write_s436m_anc_desc },
323 324 325 326 327
    // ProRes
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x1c,0x01,0x00 },
      { 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 },
328
    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
329
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
330
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
331
      NULL },
332 333
};

334
typedef struct MXFContext {
335
    AVClass *av_class;
336
    int64_t footer_partition_offset;
337
    int essence_container_count;
338
    AVRational time_base;
339
    int header_written;
340 341
    MXFIndexEntry *index_entries;
    unsigned edit_units_count;
342
    uint64_t timestamp;   ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
343
    uint8_t slice_count;  ///< index slice count minus 1 (1 if no audio, 0 otherwise)
344 345 346 347
    int last_indexed_edit_unit;
    uint64_t *body_partition_offset;
    unsigned body_partitions_count;
    int last_key_index;  ///< index of last key frame
348
    uint64_t duration;
349
    AVTimecode tc;       ///< timecode context
350 351
    AVStream *timecode_track;
    int timecode_base;       ///< rounded time code base (25 or 30)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
352
    int edit_unit_byte_count; ///< fixed edit unit byte count
353
    int content_package_rate; ///< content package rate in system element, see SMPTE 326M
354
    uint64_t body_offset;
355 356
    uint32_t instance_number;
    uint8_t umid[16];        ///< unique material identifier
357
    int channel_count;
358
    int signal_standard;
359
    uint32_t tagged_value_count;
360
    AVRational audio_edit_rate;
361
    int store_user_comments;
362
    int track_instance_count; // used to generate MXFTrack uuids
363
    int cbr_index;           ///< use a constant bitrate index
364
} MXFContext;
365

366
static const uint8_t uuid_base[]            = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
367
static const uint8_t umid_ul[]              = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 };
368 369 370 371

/**
 * complete key for operation pattern, partitions, and primer pack
 */
372
static const uint8_t op1a_ul[]                     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x01,0x09,0x00 };
373
static const uint8_t opatom_ul[]                   = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x02,0x01,0x10,0x03,0x00,0x00 };
374 375 376 377
static const uint8_t footer_partition_key[]        = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }; // ClosedComplete
static const uint8_t primer_pack_key[]             = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x05,0x01,0x00 };
static const uint8_t index_table_segment_key[]     = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 };
static const uint8_t random_index_pack_key[]       = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 };
378 379
static const uint8_t header_open_partition_key[]   = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }; // OpenIncomplete
static const uint8_t header_closed_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }; // ClosedComplete
380
static const uint8_t klv_fill_key[]                = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 };
381
static const uint8_t body_partition_key[]          = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }; // ClosedComplete
382

383 384 385 386
/**
 * partial key for header metadata
 */
static const uint8_t header_metadata_key[]  = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01 };
387
static const uint8_t multiple_desc_ul[]     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x0D,0x01,0x03,0x01,0x02,0x7F,0x01,0x00 };
388

389 390
/**
 * SMPTE RP210 http://www.smpte-ra.org/mdd/index.html
391
 *             https://smpte-ra.org/sites/default/files/Labels.xml
392 393 394 395 396 397
 */
static const MXFLocalTagPair mxf_local_tag_batch[] = {
    // preface set
    { 0x3C0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x15,0x02,0x00,0x00,0x00,0x00}}, /* Instance UID */
    { 0x3B02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x02,0x04,0x00,0x00}}, /* Last Modified Date */
    { 0x3B05, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x01,0x05,0x00,0x00,0x00}}, /* Version */
398
    { 0x3B07, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x01,0x04,0x00,0x00,0x00}}, /* Object Model Version */
399 400 401 402 403 404 405 406 407
    { 0x3B06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x04,0x00,0x00}}, /* Identifications reference */
    { 0x3B03, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x01,0x00,0x00}}, /* Content Storage reference */
    { 0x3B09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x02,0x02,0x03,0x00,0x00,0x00,0x00}}, /* Operational Pattern UL */
    { 0x3B0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x02,0x02,0x10,0x02,0x01,0x00,0x00}}, /* Essence Containers UL batch */
    { 0x3B0B, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x02,0x02,0x10,0x02,0x02,0x00,0x00}}, /* DM Schemes UL batch */
    // Identification
    { 0x3C09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x01,0x00,0x00,0x00}}, /* This Generation UID */
    { 0x3C01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x02,0x01,0x00,0x00}}, /* Company Name */
    { 0x3C02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x03,0x01,0x00,0x00}}, /* Product Name */
408
    { 0x3C03, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x04,0x00,0x00,0x00}}, /* Product Version */
409
    { 0x3C04, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x05,0x01,0x00,0x00}}, /* Version String */
410 411
    { 0x3C05, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x07,0x00,0x00,0x00}}, /* Product ID */
    { 0x3C06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x02,0x03,0x00,0x00}}, /* Modification Date */
412 413
    { 0x3C07, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x0A,0x00,0x00,0x00}}, /* Toolkit Version */
    { 0x3C08, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x06,0x01,0x00,0x00}}, /* Platform */
414 415
    // Content Storage
    { 0x1901, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x05,0x01,0x00,0x00}}, /* Package strong reference batch */
416
    { 0x1902, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x05,0x02,0x00,0x00}}, /* Package strong reference batch */
417 418 419 420 421 422 423
    // Essence Container Data
    { 0x2701, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x06,0x01,0x00,0x00,0x00}}, /* Linked Package UID */
    { 0x3F07, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x01,0x03,0x04,0x04,0x00,0x00,0x00,0x00}}, /* BodySID */
    // Package
    { 0x4401, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x15,0x10,0x00,0x00,0x00,0x00}}, /* Package UID */
    { 0x4405, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x01,0x03,0x00,0x00}}, /* Package Creation Date */
    { 0x4404, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x02,0x05,0x00,0x00}}, /* Package Modified Date */
424
    { 0x4402, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x03,0x03,0x02,0x01,0x00,0x00,0x00}}, /* Package Name */
425 426 427 428
    { 0x4403, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x05,0x00,0x00}}, /* Tracks Strong reference array */
    { 0x4701, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x03,0x00,0x00}}, /* Descriptor */
    // Track
    { 0x4801, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x01,0x07,0x01,0x01,0x00,0x00,0x00,0x00}}, /* Track ID */
429
    { 0x4804, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x01,0x04,0x01,0x03,0x00,0x00,0x00,0x00}}, /* Track Number */
430 431 432 433 434 435 436 437
    { 0x4B01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x30,0x04,0x05,0x00,0x00,0x00,0x00}}, /* Edit Rate */
    { 0x4B02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x03,0x00,0x00}}, /* Origin */
    { 0x4803, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x04,0x00,0x00}}, /* Sequence reference */
    // Sequence
    { 0x0201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x07,0x01,0x00,0x00,0x00,0x00,0x00}}, /* Data Definition UL */
    { 0x0202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x02,0x01,0x01,0x03,0x00,0x00}}, /* Duration */
    { 0x1001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x09,0x00,0x00}}, /* Structural Components reference array */
    // Source Clip
438
    { 0x1201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x04,0x00,0x00}}, /* Start position */
439 440
    { 0x1101, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x01,0x00,0x00,0x00}}, /* SourcePackageID */
    { 0x1102, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x02,0x00,0x00,0x00}}, /* SourceTrackID */
441 442 443 444
    // Timecode Component
    { 0x1501, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x05,0x00,0x00}}, /* Start Time Code */
    { 0x1502, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x04,0x01,0x01,0x02,0x06,0x00,0x00}}, /* Rounded Time Code Base */
    { 0x1503, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x04,0x01,0x01,0x05,0x00,0x00,0x00}}, /* Drop Frame */
445 446
    // File Descriptor
    { 0x3F01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x04,0x06,0x0B,0x00,0x00}}, /* Sub Descriptors reference array */
447 448
    { 0x3006, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x06,0x01,0x01,0x03,0x05,0x00,0x00,0x00}}, /* Linked Track ID */
    { 0x3001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x00,0x00,0x00,0x00}}, /* SampleRate */
449
    { 0x3002, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x02,0x00,0x00,0x00,0x00}}, /* ContainerDuration */
450 451
    { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* Essence Container */
    // Generic Picture Essence Descriptor
452
    { 0x320C, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Frame Layout */
453
    { 0x320D, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x02,0x05,0x00,0x00,0x00}}, /* Video Line Map */
454 455
    { 0x3203, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x02,0x02,0x00,0x00,0x00}}, /* Stored Width */
    { 0x3202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x02,0x01,0x00,0x00,0x00}}, /* Stored Height */
456 457 458 459 460
    { 0x3216, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x03,0x02,0x08,0x00,0x00,0x00}}, /* Stored F2 Offset */
    { 0x3205, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x08,0x00,0x00,0x00}}, /* Sampled Width */
    { 0x3204, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x07,0x00,0x00,0x00}}, /* Sampled Height */
    { 0x3206, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x09,0x00,0x00,0x00}}, /* Sampled X Offset */
    { 0x3207, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0A,0x00,0x00,0x00}}, /* Sampled Y Offset */
461 462
    { 0x3209, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0C,0x00,0x00,0x00}}, /* Display Width */
    { 0x3208, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0B,0x00,0x00,0x00}}, /* Display Height */
463
    { 0x320A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0D,0x00,0x00,0x00}}, /* Display X offset */
464
    { 0x320B, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0E,0x00,0x00,0x00}}, /* Presentation Y offset */
465
    { 0x3217, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x03,0x02,0x07,0x00,0x00,0x00}}, /* Display F2 offset */
466
    { 0x320E, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x00,0x00,0x00}}, /* Aspect Ratio */
467
    { 0x3210, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x02,0x01,0x01,0x01,0x02,0x00}}, /* Transfer characteristic */
468 469
    { 0x3213, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x18,0x01,0x02,0x00,0x00,0x00,0x00}}, /* Image Start Offset */
    { 0x3214, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x18,0x01,0x03,0x00,0x00,0x00,0x00}}, /* Image End Offset */
470
    { 0x3201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}}, /* Picture Essence Coding */
471
    { 0x3212, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x01,0x06,0x00,0x00,0x00}}, /* Field Dominance (Opt) */
472
    { 0x3215, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x05,0x01,0x13,0x00,0x00,0x00,0x00}}, /* Signal Standard */
473 474 475
    // CDCI Picture Essence Descriptor
    { 0x3301, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x03,0x0A,0x00,0x00,0x00}}, /* Component Depth */
    { 0x3302, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x05,0x00,0x00,0x00}}, /* Horizontal Subsampling */
476
    { 0x3308, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x01,0x10,0x00,0x00,0x00}}, /* Vertical Subsampling */
477
    { 0x3303, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x06,0x00,0x00,0x00}}, /* Color Siting */
478
    { 0x3307, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x18,0x01,0x04,0x00,0x00,0x00,0x00}}, /* Padding Bits */
479 480 481
    { 0x3304, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x03,0x03,0x00,0x00,0x00}}, /* Black Ref level */
    { 0x3305, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x03,0x04,0x00,0x00,0x00}}, /* White Ref level */
    { 0x3306, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x03,0x05,0x00,0x00,0x00}}, /* Color Range */
482
    // Generic Sound Essence Descriptor
483
    { 0x3D02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Locked/Unlocked */
484
    { 0x3D03, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x01,0x01,0x01,0x00,0x00}}, /* Audio sampling rate */
485
    { 0x3D04, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x02,0x01,0x01,0x03,0x00,0x00,0x00}}, /* Audio Ref Level */
486 487
    { 0x3D07, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x01,0x01,0x04,0x00,0x00,0x00}}, /* ChannelCount */
    { 0x3D01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x03,0x04,0x00,0x00,0x00}}, /* Quantization bits */
488
    { 0x3D06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x02,0x04,0x02,0x00,0x00,0x00,0x00}}, /* Sound Essence Compression */
489 490 491 492
    // Index Table Segment
    { 0x3F0B, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x05,0x30,0x04,0x06,0x00,0x00,0x00,0x00}}, /* Index Edit Rate */
    { 0x3F0C, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x07,0x02,0x01,0x03,0x01,0x0A,0x00,0x00}}, /* Index Start Position */
    { 0x3F0D, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x07,0x02,0x02,0x01,0x01,0x02,0x00,0x00}}, /* Index Duration */
493
    { 0x3F05, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x06,0x02,0x01,0x00,0x00,0x00,0x00}}, /* Edit Unit Byte Count */
494 495 496 497
    { 0x3F06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x01,0x03,0x04,0x05,0x00,0x00,0x00,0x00}}, /* IndexSID */
    { 0x3F08, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x04,0x04,0x01,0x01,0x00,0x00,0x00}}, /* Slice Count */
    { 0x3F09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x04,0x04,0x01,0x06,0x00,0x00,0x00}}, /* Delta Entry Array */
    { 0x3F0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x04,0x04,0x02,0x05,0x00,0x00,0x00}}, /* Index Entry Array */
Baptiste Coudurier's avatar
Baptiste Coudurier committed
498 499
    // MPEG video Descriptor
    { 0x8000, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0B,0x00,0x00}}, /* BitRate */
500 501 502
    { 0x8003, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x05,0x00,0x00}}, /* LowDelay */
    { 0x8004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x06,0x00,0x00}}, /* ClosedGOP */
    { 0x8006, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x08,0x00,0x00}}, /* MaxGOP */
503
    { 0x8007, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0A,0x00,0x00}}, /* ProfileAndLevel */
504
    { 0x8008, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x09,0x00,0x00}}, /* BPictureCount */
505 506 507
    // Wave Audio Essence Descriptor
    { 0x3D09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x03,0x05,0x00,0x00,0x00}}, /* Average Bytes Per Second */
    { 0x3D0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x02,0x01,0x00,0x00,0x00}}, /* Block Align */
508 509
};

510 511 512 513 514 515 516
static const MXFLocalTagPair mxf_avc_subdescriptor_local_tags[] = {
    { 0x8100, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00}}, /* SubDescriptors */
    { 0x8200, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0E,0x00,0x00}}, /* AVC Decoding Delay */
    { 0x8201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0A,0x00,0x00}}, /* AVC Profile */
    { 0x8202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0D,0x00,0x00}}, /* AVC Level */
};

517 518 519 520 521 522
static const MXFLocalTagPair mxf_user_comments_local_tag[] = {
    { 0x4406, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0C,0x00,0x00,0x00}}, /* User Comments */
    { 0x5001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x09,0x01,0x00,0x00}}, /* Name */
    { 0x5003, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0A,0x01,0x00,0x00}}, /* Value */
};

523
static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value)
524
{
525 526 527
    avio_write(pb, uuid_base, 12);
    avio_wb16(pb, type);
    avio_wb16(pb, value);
528 529
}

530
static void mxf_write_umid(AVFormatContext *s, int type)
531
{
532
    MXFContext *mxf = s->priv_data;
533 534 535 536
    avio_write(s->pb, umid_ul, 13);
    avio_wb24(s->pb, mxf->instance_number);
    avio_write(s->pb, mxf->umid, 15);
    avio_w8(s->pb, type);
537
}
538

539
static void mxf_write_refs_count(AVIOContext *pb, int ref_count)
540
{
541 542
    avio_wb32(pb, ref_count);
    avio_wb32(pb, 16);
543 544
}

545 546 547 548 549 550 551 552
static int klv_ber_length(uint64_t len)
{
    if (len < 128)
        return 1;
    else
        return (av_log2(len) >> 3) + 2;
}

553
static int klv_encode_ber_length(AVIOContext *pb, uint64_t len)
554 555 556 557 558
{
    // Determine the best BER size
    int size;
    if (len < 128) {
        //short form
559
        avio_w8(pb, len);
560 561 562 563 564 565
        return 1;
    }

    size = (av_log2(len) >> 3) + 1;

    // long form
566
    avio_w8(pb, 0x80 + size);
567
    while(size) {
568
        size--;
569
        avio_w8(pb, len >> 8 * size & 0xff);
570 571 572 573
    }
    return 0;
}

574
static void klv_encode_ber4_length(AVIOContext *pb, int len)
575
{
576 577
    avio_w8(pb, 0x80 + 3);
    avio_wb24(pb, len);
578 579
}

580 581 582 583 584 585
static void klv_encode_ber9_length(AVIOContext *pb, uint64_t len)
{
    avio_w8(pb, 0x80 + 8);
    avio_wb64(pb, len);
}

586
/*
587
 * Get essence container ul index
588
 */
589
static int mxf_get_essence_container_ul_index(enum AVCodecID id)
590
{
591
    int i;
592 593 594
    for (i = 0; mxf_essence_mappings[i].id; i++)
        if (mxf_essence_mappings[i].id == id)
            return mxf_essence_mappings[i].index;
595
    return -1;
596 597
}

598 599 600 601 602 603 604 605 606
static void mxf_write_local_tags(AVIOContext *pb, const MXFLocalTagPair *local_tags, int count)
{
    int i;
    for (i = 0; i < count; i++) {
        avio_wb16(pb, local_tags[i].local_tag);
        avio_write(pb, local_tags[i].uid, 16);
    }
}

607
static void mxf_write_primer_pack(AVFormatContext *s)
608
{
609
    MXFContext *mxf = s->priv_data;
610
    AVIOContext *pb = s->pb;
611
    int local_tag_number, i = 0;
612
    int avc_tags_count = 0;
613

614
    local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch);
615
    local_tag_number += mxf->store_user_comments * FF_ARRAY_ELEMS(mxf_user_comments_local_tag);
616

617 618 619 620 621 622 623 624
    for (i = 0; i < s->nb_streams; i++) {
        MXFStreamContext *sc = s->streams[i]->priv_data;
        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) {
            avc_tags_count = FF_ARRAY_ELEMS(mxf_avc_subdescriptor_local_tags);
            local_tag_number += avc_tags_count;
        }
    }

625
    avio_write(pb, primer_pack_key, 16);
626 627
    klv_encode_ber_length(pb, local_tag_number * 18 + 8);

628 629
    avio_wb32(pb, local_tag_number); // local_tag num
    avio_wb32(pb, 18); // item size, always 18 according to the specs
630

631
    for (i = 0; i < FF_ARRAY_ELEMS(mxf_local_tag_batch); i++) {
632 633
        avio_wb16(pb, mxf_local_tag_batch[i].local_tag);
        avio_write(pb, mxf_local_tag_batch[i].uid, 16);
634
    }
635 636 637 638 639
    if (mxf->store_user_comments)
        for (i = 0; i < FF_ARRAY_ELEMS(mxf_user_comments_local_tag); i++) {
            avio_wb16(pb, mxf_user_comments_local_tag[i].local_tag);
            avio_write(pb, mxf_user_comments_local_tag[i].uid, 16);
        }
640 641
    if (avc_tags_count > 0)
        mxf_write_local_tags(pb, mxf_avc_subdescriptor_local_tags, avc_tags_count);
642 643
}

644
static void mxf_write_local_tag(AVIOContext *pb, int size, int tag)
645
{
646 647
    avio_wb16(pb, tag);
    avio_wb16(pb, size);
648 649
}

650
static void mxf_write_metadata_key(AVIOContext *pb, unsigned int value)
651
{
652 653
    avio_write(pb, header_metadata_key, 13);
    avio_wb24(pb, value);
654 655
}

656 657 658 659 660
static void mxf_free(AVFormatContext *s)
{
    int i;

    for (i = 0; i < s->nb_streams; i++) {
661
        AVStream *st = s->streams[i];
662 663 664 665
        av_freep(&st->priv_data);
    }
}

666
static const MXFCodecUL *mxf_get_data_definition_ul(int type)
667
{
668 669 670
    const MXFCodecUL *uls = ff_mxf_data_definition_uls;
    while (uls->uid[0]) {
        if (type == uls->id)
671
            break;
672
        uls++;
673 674 675 676
    }
    return uls;
}

677 678 679 680
//one EC -> one descriptor. N ECs -> MultipleDescriptor + N descriptors
#define DESCRIPTOR_COUNT(essence_container_count) \
    (essence_container_count > 1 ? essence_container_count + 1 : essence_container_count)

681
static void mxf_write_essence_container_refs(AVFormatContext *s)
682
{
683
    MXFContext *c = s->priv_data;
684
    AVIOContext *pb = s->pb;
685
    int i;
686

687
    mxf_write_refs_count(pb, DESCRIPTOR_COUNT(c->essence_container_count));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
688
    av_log(s,AV_LOG_DEBUG, "essence container count:%d\n", c->essence_container_count);
689
    for (i = 0; i < s->nb_streams; i++) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
690
        MXFStreamContext *sc = s->streams[i]->priv_data;
691 692 693
        // check first track of essence container type and only write it once
        if (sc->track_essence_element_key[15] != 0)
            continue;
694
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
695 696
        if (c->essence_container_count == 1)
            break;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
697
    }
698 699 700

    if (c->essence_container_count > 1)
        avio_write(pb, multiple_desc_ul, 16);
701 702
}

703 704 705
static void mxf_write_preface(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
706
    AVIOContext *pb = s->pb;
707 708 709

    mxf_write_metadata_key(pb, 0x012f00);
    PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
710
    klv_encode_ber_length(pb, 138 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
711 712 713 714 715 716

    // write preface set uid
    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, Preface, 0);
    PRINT_KEY(s, "preface uid", pb->buf_ptr - 16);

717
    // last modified date
718
    mxf_write_local_tag(pb, 8, 0x3B02);
719
    avio_wb64(pb, mxf->timestamp);
720 721 722

    // write version
    mxf_write_local_tag(pb, 2, 0x3B05);
723
    avio_wb16(pb, 259); // v1.3
724

725 726 727 728
    // Object Model Version
    mxf_write_local_tag(pb, 4, 0x3B07);
    avio_wb32(pb, 1);

729 730 731 732 733 734 735 736 737
    // write identification_refs
    mxf_write_local_tag(pb, 16 + 8, 0x3B06);
    mxf_write_refs_count(pb, 1);
    mxf_write_uuid(pb, Identification, 0);

    // write content_storage_refs
    mxf_write_local_tag(pb, 16, 0x3B03);
    mxf_write_uuid(pb, ContentStorage, 0);

738
    // operational pattern
739
    mxf_write_local_tag(pb, 16, 0x3B09);
740 741 742 743
    if (s->oformat == &ff_mxf_opatom_muxer)
        avio_write(pb, opatom_ul, 16);
    else
        avio_write(pb, op1a_ul, 16);
744 745

    // write essence_container_refs
746
    mxf_write_local_tag(pb, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A);
747
    mxf_write_essence_container_refs(s);
748 749 750

    // write dm_scheme_refs
    mxf_write_local_tag(pb, 8, 0x3B0B);
751
    avio_wb64(pb, 0);
752 753
}

754
/*
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
 * Returns the length of the UTF-16 string, in 16-bit characters, that would result
 * from decoding the utf-8 string.
 */
static uint64_t mxf_utf16len(const char *utf8_str)
{
    const uint8_t *q = utf8_str;
    uint64_t size = 0;
    while (*q) {
        uint32_t ch;
        GET_UTF8(ch, *q++, goto invalid;)
        if (ch < 0x10000)
            size++;
        else
            size += 2;
        continue;
invalid:
771
        av_log(NULL, AV_LOG_ERROR, "Invalid UTF8 sequence in mxf_utf16len\n\n");
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
    }
    size += 1;
    return size;
}

/*
 * Returns the calculated length a local tag containing an utf-8 string as utf-16
 */
static int mxf_utf16_local_tag_length(const char *utf8_str)
{
    uint64_t size;

    if (!utf8_str)
        return 0;

    size = mxf_utf16len(utf8_str);
    if (size >= UINT16_MAX/2) {
        av_log(NULL, AV_LOG_ERROR, "utf16 local tag size %"PRIx64" invalid (too large), ignoring\n", size);
        return 0;
    }

    return 4 + size * 2;
}

/*
 * Write a local tag containing an utf-8 string as utf-16
798
 */
799
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
800
{
801 802 803 804 805 806 807
    uint64_t size = mxf_utf16len(value);

    if (size >= UINT16_MAX/2) {
        av_log(NULL, AV_LOG_ERROR, "utf16 local tag size %"PRIx64" invalid (too large), ignoring\n", size);
        return;
    }

808
    mxf_write_local_tag(pb, size*2, tag);
809
    avio_put_str16be(pb, value);
810 811
}

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
static void store_version(AVFormatContext *s){
    AVIOContext *pb = s->pb;

    if (s->flags & AVFMT_FLAG_BITEXACT) {
        avio_wb16(pb, 0); // major
        avio_wb16(pb, 0); // minor
        avio_wb16(pb, 0); // tertiary
    } else {
        avio_wb16(pb, LIBAVFORMAT_VERSION_MAJOR); // major
        avio_wb16(pb, LIBAVFORMAT_VERSION_MINOR); // minor
        avio_wb16(pb, LIBAVFORMAT_VERSION_MICRO); // tertiary
    }
    avio_wb16(pb, 0); // patch
    avio_wb16(pb, 0); // release
}

828 829
static void mxf_write_identification(AVFormatContext *s)
{
830
    MXFContext *mxf = s->priv_data;
831
    AVIOContext *pb = s->pb;
832
    const char *company = "FFmpeg";
833
    const char *product = s->oformat != &ff_mxf_opatom_muxer ? "OP1a Muxer" : "OPAtom Muxer";
834
    const char *version;
835
    int length;
836 837 838 839

    mxf_write_metadata_key(pb, 0x013000);
    PRINT_KEY(s, "identification key", pb->buf_ptr - 16);

840
    version = s->flags & AVFMT_FLAG_BITEXACT ?
841
        "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
842
    length = 100 +mxf_utf16_local_tag_length(company) +
843 844
                  mxf_utf16_local_tag_length(product) +
                  mxf_utf16_local_tag_length(version);
845 846 847 848 849 850
    klv_encode_ber_length(pb, length);

    // write uid
    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, Identification, 0);
    PRINT_KEY(s, "identification uid", pb->buf_ptr - 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
851

852 853 854
    // write generation uid
    mxf_write_local_tag(pb, 16, 0x3C09);
    mxf_write_uuid(pb, Identification, 1);
855 856
    mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
    mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
857 858 859 860

    mxf_write_local_tag(pb, 10, 0x3C03); // Product Version
    store_version(s);

861
    mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
862 863 864 865 866

    // write product uid
    mxf_write_local_tag(pb, 16, 0x3C05);
    mxf_write_uuid(pb, Identification, 2);

867
    // modification date
868
    mxf_write_local_tag(pb, 8, 0x3C06);
869
    avio_wb64(pb, mxf->timestamp);
870 871 872

    mxf_write_local_tag(pb, 10, 0x3C07); // Toolkit Version
    store_version(s);
873 874
}

875
static void mxf_write_content_storage(AVFormatContext *s, MXFPackage *packages, int package_count)
876
{
877
    AVIOContext *pb = s->pb;
878
    int i;
879 880 881

    mxf_write_metadata_key(pb, 0x011800);
    PRINT_KEY(s, "content storage key", pb->buf_ptr - 16);
882
    klv_encode_ber_length(pb, 60 + (16 * package_count));
883 884 885 886 887

    // write uid
    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, ContentStorage, 0);
    PRINT_KEY(s, "content storage uid", pb->buf_ptr - 16);
888

889
    // write package reference
890 891 892 893 894
    mxf_write_local_tag(pb, 16 * package_count + 8, 0x1901);
    mxf_write_refs_count(pb, package_count);
    for (i = 0; i < package_count; i++) {
        mxf_write_uuid(pb, packages[i].type, packages[i].instance);
    }
895 896 897 898 899

    // write essence container data
    mxf_write_local_tag(pb, 8 + 16, 0x1902);
    mxf_write_refs_count(pb, 1);
    mxf_write_uuid(pb, EssenceContainerData, 0);
900 901
}

902
static void mxf_write_track(AVFormatContext *s, AVStream *st, MXFPackage *package)
903
{
904
    MXFContext *mxf = s->priv_data;
905
    AVIOContext *pb = s->pb;
906
    MXFStreamContext *sc = st->priv_data;
907 908 909 910 911 912 913

    mxf_write_metadata_key(pb, 0x013b00);
    PRINT_KEY(s, "track key", pb->buf_ptr - 16);
    klv_encode_ber_length(pb, 80);

    // write track uid
    mxf_write_local_tag(pb, 16, 0x3C0A);
914
    mxf_write_uuid(pb, Track, mxf->track_instance_count);
915
    PRINT_KEY(s, "track uid", pb->buf_ptr - 16);
916

917 918
    // write track id
    mxf_write_local_tag(pb, 4, 0x4801);
919
    avio_wb32(pb, st->index+2);
920

921
    // write track number
922
    mxf_write_local_tag(pb, 4, 0x4804);
923
    if (package->type == MaterialPackage)
924
        avio_wb32(pb, 0); // track number of material package is 0
925
    else
926
        avio_write(pb, sc->track_essence_element_key + 12, 4);
927

928
    // write edit rate
929
    mxf_write_local_tag(pb, 8, 0x4B01);
930

931
    if (st == mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer) {
932 933 934 935 936 937
        avio_wb32(pb, mxf->tc.rate.num);
        avio_wb32(pb, mxf->tc.rate.den);
    } else {
        avio_wb32(pb, mxf->time_base.den);
        avio_wb32(pb, mxf->time_base.num);
    }
938 939 940

    // write origin
    mxf_write_local_tag(pb, 8, 0x4B02);
941
    avio_wb64(pb, 0);
942 943 944

    // write sequence refs
    mxf_write_local_tag(pb, 16, 0x4803);
945
    mxf_write_uuid(pb, Sequence, mxf->track_instance_count);
946 947
}

948 949 950
static const uint8_t smpte_12m_timecode_track_data_ul[] = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x01,0x01,0x00,0x00,0x00 };

static void mxf_write_common_fields(AVFormatContext *s, AVStream *st)
951
{
952
    MXFContext *mxf = s->priv_data;
953
    AVIOContext *pb = s->pb;
954

955 956
    // find data define uls
    mxf_write_local_tag(pb, 16, 0x0201);
957
    if (st == mxf->timecode_track)
958
        avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
959
    else {
960
        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codecpar->codec_type);
961
        avio_write(pb, data_def_ul->uid, 16);
962
    }
963 964 965

    // write duration
    mxf_write_local_tag(pb, 8, 0x0202);
966

967
    if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
968 969 970 971
        avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count);
    } else {
        avio_wb64(pb, mxf->duration);
    }
972 973
}

974
static void mxf_write_sequence(AVFormatContext *s, AVStream *st, MXFPackage *package)
975
{
976
    MXFContext *mxf = s->priv_data;
977
    AVIOContext *pb = s->pb;
978
    enum MXFMetadataSetType component;
979 980 981 982 983 984

    mxf_write_metadata_key(pb, 0x010f00);
    PRINT_KEY(s, "sequence key", pb->buf_ptr - 16);
    klv_encode_ber_length(pb, 80);

    mxf_write_local_tag(pb, 16, 0x3C0A);
985
    mxf_write_uuid(pb, Sequence, mxf->track_instance_count);
986 987

    PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
988
    mxf_write_common_fields(s, st);
989 990 991 992

    // write structural component
    mxf_write_local_tag(pb, 16 + 8, 0x1001);
    mxf_write_refs_count(pb, 1);
993 994 995
    if (st == mxf->timecode_track)
        component = TimecodeComponent;
    else
996
        component = SourceClip;
997 998

    mxf_write_uuid(pb, component, mxf->track_instance_count);
999 1000
}

1001
static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, MXFPackage *package)
1002 1003
{
    MXFContext *mxf = s->priv_data;
1004
    AVIOContext *pb = s->pb;
1005 1006 1007 1008 1009 1010

    mxf_write_metadata_key(pb, 0x011400);
    klv_encode_ber_length(pb, 75);

    // UID
    mxf_write_local_tag(pb, 16, 0x3C0A);
1011
    mxf_write_uuid(pb, TimecodeComponent, mxf->track_instance_count);
1012 1013 1014 1015 1016

    mxf_write_common_fields(s, st);

    // Start Time Code
    mxf_write_local_tag(pb, 8, 0x1501);
1017
    avio_wb64(pb, mxf->tc.start);
1018 1019 1020

    // Rounded Time Code Base
    mxf_write_local_tag(pb, 2, 0x1502);
1021
    avio_wb16(pb, mxf->timecode_base);
1022 1023 1024

    // Drop Frame
    mxf_write_local_tag(pb, 1, 0x1503);
1025
    avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
1026 1027
}

1028
static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, MXFPackage *package)
1029
{
1030
    MXFContext *mxf = s->priv_data;
1031
    AVIOContext *pb = s->pb;
1032 1033 1034 1035 1036 1037 1038 1039
    int i;

    mxf_write_metadata_key(pb, 0x011100);
    PRINT_KEY(s, "sturctural component key", pb->buf_ptr - 16);
    klv_encode_ber_length(pb, 108);

    // write uid
    mxf_write_local_tag(pb, 16, 0x3C0A);
1040
    mxf_write_uuid(pb, SourceClip, mxf->track_instance_count);
1041 1042

    PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
1043
    mxf_write_common_fields(s, st);
1044 1045 1046

    // write start_position
    mxf_write_local_tag(pb, 8, 0x1201);
1047
    avio_wb64(pb, 0);
1048

1049
    // write source package uid, end of the reference
1050
    mxf_write_local_tag(pb, 32, 0x1101);
1051
    if (!package->ref) {
1052
        for (i = 0; i < 4; i++)
1053
            avio_wb64(pb, 0);
1054
    } else
1055
        mxf_write_umid(s, package->ref->instance);
1056

1057
    // write source track id
1058
    mxf_write_local_tag(pb, 4, 0x1102);
1059
    if (package->type == SourcePackage && !package->ref)
1060
        avio_wb32(pb, 0);
1061
    else
1062
        avio_wb32(pb, st->index+2);
1063 1064
}

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
static void mxf_write_tape_descriptor(AVFormatContext *s)
{
    AVIOContext *pb = s->pb;

    mxf_write_metadata_key(pb, 0x012e00);
    PRINT_KEY(s, "tape descriptor key", pb->buf_ptr - 16);
    klv_encode_ber_length(pb, 20);
    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, TapeDescriptor, 0);
    PRINT_KEY(s, "tape_desc uid", pb->buf_ptr - 16);
}


1078 1079
static void mxf_write_multi_descriptor(AVFormatContext *s)
{
1080
    MXFContext *mxf = s->priv_data;
1081
    AVIOContext *pb = s->pb;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1082
    const uint8_t *ul;
1083 1084 1085 1086
    int i;

    mxf_write_metadata_key(pb, 0x014400);
    PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16);
1087
    klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams);
1088 1089 1090 1091 1092 1093 1094

    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, MultipleDescriptor, 0);
    PRINT_KEY(s, "multi_desc uid", pb->buf_ptr - 16);

    // write sample rate
    mxf_write_local_tag(pb, 8, 0x3001);
1095 1096
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
1097 1098 1099

    // write essence container ul
    mxf_write_local_tag(pb, 16, 0x3004);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1100 1101
    if (mxf->essence_container_count > 1)
        ul = multiple_desc_ul;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1102 1103 1104 1105
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
        ul = mxf_essence_container_uls[sc->index].container_ul;
    }
1106
    avio_write(pb, ul, 16);
1107 1108 1109 1110

    // write sub descriptor refs
    mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01);
    mxf_write_refs_count(pb, s->nb_streams);
1111
    for (i = 0; i < s->nb_streams; i++)
1112 1113 1114
        mxf_write_uuid(pb, SubDescriptor, i);
}

1115
static int64_t mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key)
1116
{
1117
    MXFContext *mxf = s->priv_data;
1118
    MXFStreamContext *sc = st->priv_data;
1119
    AVIOContext *pb = s->pb;
1120
    int64_t pos;
1121

1122
    avio_write(pb, key, 16);
1123 1124
    klv_encode_ber4_length(pb, 0);
    pos = avio_tell(pb);
1125 1126 1127 1128 1129

    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, SubDescriptor, st->index);

    mxf_write_local_tag(pb, 4, 0x3006);
1130
    avio_wb32(pb, st->index+2);
1131

1132
    mxf_write_local_tag(pb, 8, 0x3001);
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
    if (s->oformat == &ff_mxf_d10_muxer) {
        avio_wb32(pb, mxf->time_base.den);
        avio_wb32(pb, mxf->time_base.num);
    } else {
        if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE ||
            st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
            avio_wb32(pb, st->codecpar->sample_rate);
            avio_wb32(pb, 1);
        } else {
            avio_wb32(pb, mxf->time_base.den);
            avio_wb32(pb, mxf->time_base.num);
        }
    }
1146

1147
    mxf_write_local_tag(pb, 16, 0x3004);
1148
    avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
1149 1150

    return pos;
1151 1152
}

1153
static const UID mxf_s436m_anc_descriptor_key = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 };
1154 1155
static const UID mxf_mpegvideo_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 };
static const UID mxf_wav_descriptor_key       = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 };
1156
static const UID mxf_aes3_descriptor_key      = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 };
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1157 1158
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_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x42,0x00 };
1159

1160 1161
static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 };

1162 1163 1164 1165 1166
static int get_trc(UID ul, enum AVColorTransferCharacteristic trc)
{
    switch (trc){
    case AVCOL_TRC_GAMMA28   :
    case AVCOL_TRC_GAMMA22   :
1167
        memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x01,0x00,0x00}), 16);
1168 1169 1170
        return 0;
    case AVCOL_TRC_BT709     :
    case AVCOL_TRC_SMPTE170M :
1171
        memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00}), 16);
1172 1173
        return 0;
    case AVCOL_TRC_SMPTE240M :
1174
        memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x03,0x00,0x00}), 16);
1175 1176
        return 0;
    case AVCOL_TRC_BT1361_ECG:
1177
        memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x05,0x00,0x00}), 16);
1178 1179
        return 0;
    case AVCOL_TRC_LINEAR    :
1180
        memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x06,0x00,0x00}), 16);
1181 1182
        return 0;
    case AVCOL_TRC_SMPTE428  :
1183
        memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x08,0x04,0x01,0x01,0x01,0x01,0x07,0x00,0x00}), 16);
1184 1185 1186 1187 1188 1189
        return 0;
    default:
        return -1;
    }
}

1190
static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key)
1191
{
1192
    MXFStreamContext *sc = st->priv_data;
1193
    AVIOContext *pb = s->pb;
1194
    int stored_width  = (st->codecpar->width +15)/16*16;
1195
    int stored_height = (st->codecpar->height+15)/16*16;
1196
    int display_height;
1197
    int f1, f2;
1198
    UID transfer_ul = {0};
1199
    int64_t pos = mxf_write_generic_desc(s, st, key);
1200

1201
    get_trc(transfer_ul, st->codecpar->color_trc);
1202 1203

    mxf_write_local_tag(pb, 4, 0x3203);
1204
    avio_wb32(pb, stored_width);
1205 1206

    mxf_write_local_tag(pb, 4, 0x3202);
1207
    avio_wb32(pb, stored_height>>sc->interlaced);
1208

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
    if (s->oformat == &ff_mxf_d10_muxer) {
        //Stored F2 Offset
        mxf_write_local_tag(pb, 4, 0x3216);
        avio_wb32(pb, 0);

        //Image Start Offset
        mxf_write_local_tag(pb, 4, 0x3213);
        avio_wb32(pb, 0);

        //Image End Offset
        mxf_write_local_tag(pb, 4, 0x3214);
        avio_wb32(pb, 0);
    }

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
    //Sampled width
    mxf_write_local_tag(pb, 4, 0x3205);
    avio_wb32(pb, st->codecpar->width);

    //Samples height
    mxf_write_local_tag(pb, 4, 0x3204);
    avio_wb32(pb, st->codecpar->height>>sc->interlaced);

    //Sampled X Offset
    mxf_write_local_tag(pb, 4, 0x3206);
    avio_wb32(pb, 0);

    //Sampled Y Offset
    mxf_write_local_tag(pb, 4, 0x3207);
    avio_wb32(pb, 0);

1239
    mxf_write_local_tag(pb, 4, 0x3209);
1240
    avio_wb32(pb, st->codecpar->width);
1241

1242
    if (st->codecpar->height == 608) // PAL + VBI
1243
        display_height = 576;
1244
    else if (st->codecpar->height == 512)  // NTSC + VBI
1245 1246
        display_height = 486;
    else
1247
        display_height = st->codecpar->height;
1248

1249
    mxf_write_local_tag(pb, 4, 0x3208);
1250
    avio_wb32(pb, display_height>>sc->interlaced);
1251

1252 1253 1254 1255 1256
    // display X offset
    mxf_write_local_tag(pb, 4, 0x320A);
    avio_wb32(pb, 0);

    // display Y offset
1257
    mxf_write_local_tag(pb, 4, 0x320B);
1258
    avio_wb32(pb, (st->codecpar->height - display_height)>>sc->interlaced);
1259

1260 1261 1262 1263 1264 1265
    if (sc->interlaced) {
        //Display F2 Offset
        mxf_write_local_tag(pb, 4, 0x3217);
        avio_wb32(pb, -((st->codecpar->height - display_height)&1));
    }

1266 1267
    // component depth
    mxf_write_local_tag(pb, 4, 0x3301);
1268
    avio_wb32(pb, sc->component_depth);
1269 1270 1271

    // horizontal subsampling
    mxf_write_local_tag(pb, 4, 0x3302);
1272
    avio_wb32(pb, sc->h_chroma_sub_sample);
1273

1274
    // vertical subsampling
1275 1276
    mxf_write_local_tag(pb, 4, 0x3308);
    avio_wb32(pb, sc->v_chroma_sub_sample);
1277

1278 1279 1280 1281
    // color siting
    mxf_write_local_tag(pb, 1, 0x3303);
    avio_w8(pb, sc->color_siting);

1282 1283 1284 1285
    // Padding Bits
    mxf_write_local_tag(pb, 2, 0x3307);
    avio_wb16(pb, 0);

1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
    if (st->codecpar->color_range != AVCOL_RANGE_UNSPECIFIED) {
        int black = 0,
            white = (1<<sc->component_depth) - 1,
            color = (1<<sc->component_depth) - 1;
        if (st->codecpar->color_range == AVCOL_RANGE_MPEG) {
            black = 1   << (sc->component_depth - 4);
            white = 235 << (sc->component_depth - 8);
            color = (14 << (sc->component_depth - 4)) + 1;
        }
        mxf_write_local_tag(pb, 4, 0x3304);
        avio_wb32(pb, black);
        mxf_write_local_tag(pb, 4, 0x3305);
        avio_wb32(pb, white);
        mxf_write_local_tag(pb, 4, 0x3306);
        avio_wb32(pb, color);
    }

1303 1304 1305 1306 1307
    if (sc->signal_standard) {
        mxf_write_local_tag(pb, 1, 0x3215);
        avio_w8(pb, sc->signal_standard);
    }

1308 1309
    // frame layout
    mxf_write_local_tag(pb, 1, 0x320C);
1310
    avio_w8(pb, sc->interlaced);
1311

1312
    // video line map
1313
    switch (st->codecpar->height) {
1314
    case  576: f1 = 23; f2 = st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
1315
    case  608: f1 =  7; f2 = 320; break;
1316
    case  480: f1 = 20; f2 = st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
1317 1318 1319 1320 1321 1322
    case  512: f1 =  7; f2 = 270; break;
    case  720: f1 = 26; f2 =   0; break; // progressive
    case 1080: f1 = 21; f2 = 584; break;
    default:   f1 =  0; f2 =   0; break;
    }

1323
    if (!sc->interlaced && f2) {
1324 1325 1326 1327
        f2  = 0;
        f1 *= 2;
    }

1328 1329 1330

    mxf_write_local_tag(pb, 16, 0x320D);
    avio_wb32(pb, 2);
1331 1332
    avio_wb32(pb, 4);
    avio_wb32(pb, f1);
1333
    avio_wb32(pb, f2);
1334

1335
    mxf_write_local_tag(pb, 8, 0x320E);
1336 1337
    avio_wb32(pb, sc->aspect_ratio.num);
    avio_wb32(pb, sc->aspect_ratio.den);
1338

1339 1340 1341 1342 1343 1344
    //Transfer characteristic
    if (transfer_ul[0]) {
        mxf_write_local_tag(pb, 16, 0x3210);
        avio_write(pb, transfer_ul, 16);
    };

1345
    mxf_write_local_tag(pb, 16, 0x3201);
1346
    avio_write(pb, *sc->codec_ul, 16);
1347 1348 1349 1350 1351 1352

    if (sc->interlaced && sc->field_dominance) {
        mxf_write_local_tag(pb, 1, 0x3212);
        avio_w8(pb, sc->field_dominance);
    }

1353 1354 1355 1356 1357 1358 1359
    if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) {
        // write avc sub descriptor ref
        mxf_write_local_tag(pb, 8 + 16, 0x8100);
        mxf_write_refs_count(pb, 1);
        mxf_write_uuid(pb, AVCSubDescriptor, 0);
    }

1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
    return pos;
}

static void mxf_update_klv_size(AVIOContext *pb, int64_t pos)
{
    int64_t cur_pos = avio_tell(pb);
    int size = cur_pos - pos;
    avio_seek(pb, pos - 4, SEEK_SET);
    klv_encode_ber4_length(pb, size);
    avio_seek(pb, cur_pos, SEEK_SET);
1370 1371
}

1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
static void mxf_write_avc_subdesc(AVFormatContext *s, AVStream *st)
{
    AVIOContext *pb = s->pb;
    int64_t pos;

    avio_write(pb, mxf_avc_subdescriptor_key, 16);
    klv_encode_ber4_length(pb, 0);
    pos = avio_tell(pb);

    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, AVCSubDescriptor, 0);

    mxf_write_local_tag(pb, 1, 0x8200);
    avio_w8(pb, 0xFF); // AVC Decoding Delay, unknown

    mxf_write_local_tag(pb, 1, 0x8201);
    avio_w8(pb, st->codecpar->profile); // AVC Profile

    mxf_write_local_tag(pb, 1, 0x8202);
    avio_w8(pb, st->codecpar->level); // AVC Level

    mxf_update_klv_size(s->pb, pos);
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1396 1397
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
{
1398 1399
    int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key);
    mxf_update_klv_size(s->pb, pos);
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415

    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
        mxf_write_avc_subdesc(s, st);
    }
}

static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st)
{
    MXFStreamContext *sc = st->priv_data;
    if (sc->avc_intra) {
        mxf_write_mpegvideo_desc(s, st);
    } else {
        int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key);
        mxf_update_klv_size(s->pb, pos);
        mxf_write_avc_subdesc(s, st);
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1416 1417
}

1418 1419 1420 1421 1422 1423
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);
    mxf_update_klv_size(s->pb, pos);
}

1424 1425
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
{
1426
    AVIOContext *pb = s->pb;
1427
    MXFStreamContext *sc = st->priv_data;
1428
    int profile_and_level = (st->codecpar->profile<<4) | st->codecpar->level;
1429
    int64_t pos = mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key);
1430

1431
    if (st->codecpar->codec_id != AV_CODEC_ID_H264) {
1432 1433 1434
        // bit rate
        mxf_write_local_tag(pb, 4, 0x8000);
        avio_wb32(pb, sc->video_bit_rate);
1435

1436 1437
        // profile and level
        mxf_write_local_tag(pb, 1, 0x8007);
1438
        if (!st->codecpar->profile)
1439 1440
            profile_and_level |= 0x80; // escape bit
        avio_w8(pb, profile_and_level);
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456

        // low delay
        mxf_write_local_tag(pb, 1, 0x8003);
        avio_w8(pb, sc->low_delay);

        // closed gop
        mxf_write_local_tag(pb, 1, 0x8004);
        avio_w8(pb, sc->seq_closed_gop);

        // max gop
        mxf_write_local_tag(pb, 2, 0x8006);
        avio_wb16(pb, sc->max_gop);

        // b picture count
        mxf_write_local_tag(pb, 2, 0x8008);
        avio_wb16(pb, sc->b_picture_count);
1457
    }
1458 1459

    mxf_update_klv_size(pb, pos);
1460 1461
}

1462
static int64_t mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key)
1463
{
1464
    AVIOContext *pb = s->pb;
1465 1466
    MXFContext *mxf = s->priv_data;
    int show_warnings = !mxf->footer_partition_offset;
1467
    int64_t pos = mxf_write_generic_desc(s, st, key);
1468

1469
    if (s->oformat == &ff_mxf_opatom_muxer) {
1470 1471 1472
        mxf_write_local_tag(pb, 8, 0x3002);
        avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count);
    }
1473

1474
    // audio locked
1475
    mxf_write_local_tag(pb, 1, 0x3D02);
1476
    avio_w8(pb, 1);
1477 1478 1479

    // write audio sampling rate
    mxf_write_local_tag(pb, 8, 0x3D03);
1480
    avio_wb32(pb, st->codecpar->sample_rate);
1481
    avio_wb32(pb, 1);
1482

1483 1484 1485 1486 1487
    if (s->oformat == &ff_mxf_d10_muxer) {
        mxf_write_local_tag(pb, 1, 0x3D04);
        avio_w8(pb, 0);
    }

1488
    mxf_write_local_tag(pb, 4, 0x3D07);
1489
    if (mxf->channel_count == -1) {
1490
        if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codecpar->channels != 4) && (st->codecpar->channels != 8))
1491
            av_log(s, AV_LOG_WARNING, "the number of audio channels shall be 4 or 8 : the output will not comply to MXF D-10 specs, use -d10_channelcount to fix this\n");
1492
        avio_wb32(pb, st->codecpar->channels);
1493
    } else if (s->oformat == &ff_mxf_d10_muxer) {
1494
        if (show_warnings && (mxf->channel_count < st->codecpar->channels))
1495
            av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n");
1496
        if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8))
1497
            av_log(s, AV_LOG_WARNING, "d10_channelcount shall be set to 4 or 8 : the output will not comply to MXF D-10 specs\n");
1498 1499
        avio_wb32(pb, mxf->channel_count);
    } else {
1500
        avio_wb32(pb, st->codecpar->channels);
1501
    }
1502 1503

    mxf_write_local_tag(pb, 4, 0x3D01);
1504
    avio_wb32(pb, av_get_bits_per_sample(st->codecpar->codec_id));
1505 1506

    return pos;
1507 1508
}

1509
static int64_t mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key)
1510
{
1511
    AVIOContext *pb = s->pb;
1512
    int64_t pos = mxf_write_generic_sound_common(s, st, key);
1513 1514

    mxf_write_local_tag(pb, 2, 0x3D0A);
1515
    avio_wb16(pb, st->codecpar->block_align);
1516 1517 1518

    // avg bytes per sec
    mxf_write_local_tag(pb, 4, 0x3D09);
1519
    avio_wb32(pb, st->codecpar->block_align*st->codecpar->sample_rate);
1520 1521

    return pos;
1522 1523
}

1524
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st)
1525
{
1526 1527
    int64_t pos = mxf_write_wav_common(s, st, mxf_wav_descriptor_key);
    mxf_update_klv_size(s->pb, pos);
1528
}
1529

1530 1531
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st)
{
1532 1533
    int64_t pos = mxf_write_wav_common(s, st, mxf_aes3_descriptor_key);
    mxf_update_klv_size(s->pb, pos);
1534 1535
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1536 1537
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st)
{
1538 1539
    int64_t pos = mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key);
    mxf_update_klv_size(s->pb, pos);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1540 1541
}

1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
static const uint8_t mxf_indirect_value_utf16le[] = { 0x4c,0x00,0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x06,0x0e,0x2b,0x34,0x01,0x04,0x01,0x01 };

static int mxf_write_tagged_value(AVFormatContext *s, const char* name, const char* value)
{
    MXFContext *mxf = s->priv_data;
    AVIOContext *pb = s->pb;
    int name_size = mxf_utf16_local_tag_length(name);
    int indirect_value_size = 13 + mxf_utf16_local_tag_length(value);

    if (!name_size || indirect_value_size == 13)
        return 1;

    mxf_write_metadata_key(pb, 0x013f00);
    klv_encode_ber_length(pb, 24 + name_size + indirect_value_size);

    // write instance UID
    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, TaggedValue, mxf->tagged_value_count);

    // write name
    mxf_write_local_tag_utf16(pb, 0x5001, name); // Name

    // write indirect value
    mxf_write_local_tag(pb, indirect_value_size, 0x5003);
    avio_write(pb, mxf_indirect_value_utf16le, 17);
    avio_put_str16le(pb, value);

    mxf->tagged_value_count++;
    return 0;
}

static int mxf_write_user_comments(AVFormatContext *s, const AVDictionary *m)
{
    MXFContext *mxf = s->priv_data;
    AVDictionaryEntry *t = NULL;
    int count = 0;

    while ((t = av_dict_get(m, "comment_", t, AV_DICT_IGNORE_SUFFIX))) {
        if (mxf->tagged_value_count >= UINT16_MAX) {
            av_log(s, AV_LOG_ERROR, "too many tagged values, ignoring remaining\n");
            return count;
        }

        if (mxf_write_tagged_value(s, t->key + 8, t->value) == 0)
            count++;
    }
    return count;
}

1591
static void mxf_write_package(AVFormatContext *s, MXFPackage *package)
1592
{
1593
    MXFContext *mxf = s->priv_data;
1594
    AVIOContext *pb = s->pb;
1595
    int i, track_count = s->nb_streams+1;
1596
    int name_size = mxf_utf16_local_tag_length(package->name);
1597
    int user_comment_count = 0;
1598

1599
    if (package->type == MaterialPackage) {
1600 1601
        if (mxf->store_user_comments)
            user_comment_count = mxf_write_user_comments(s, s->metadata);
1602 1603
        mxf_write_metadata_key(pb, 0x013600);
        PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
1604
        klv_encode_ber_length(pb, 92 + name_size + (16*track_count) + (16*user_comment_count) + 12LL*mxf->store_user_comments);
1605 1606 1607
    } else {
        mxf_write_metadata_key(pb, 0x013700);
        PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
1608
        klv_encode_ber_length(pb, 112 + name_size + (16*track_count) + 12LL*mxf->store_user_comments); // 20 bytes length for descriptor reference
1609 1610 1611 1612
    }

    // write uid
    mxf_write_local_tag(pb, 16, 0x3C0A);
1613 1614
    mxf_write_uuid(pb, package->type, package->instance);
    av_log(s, AV_LOG_DEBUG, "package type:%d\n", package->type);
1615 1616 1617 1618
    PRINT_KEY(s, "package uid", pb->buf_ptr - 16);

    // write package umid
    mxf_write_local_tag(pb, 32, 0x4401);
1619
    mxf_write_umid(s, package->instance);
1620 1621
    PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16);

1622 1623
    // package name
    if (name_size)
1624
        mxf_write_local_tag_utf16(pb, 0x4402, package->name);
1625

1626
    // package creation date
1627
    mxf_write_local_tag(pb, 8, 0x4405);
1628
    avio_wb64(pb, mxf->timestamp);
1629

1630
    // package modified date
1631
    mxf_write_local_tag(pb, 8, 0x4404);
1632
    avio_wb64(pb, mxf->timestamp);
1633 1634

    // write track refs
1635 1636
    mxf_write_local_tag(pb, track_count*16 + 8, 0x4403);
    mxf_write_refs_count(pb, track_count);
1637 1638 1639
    // these are the uuids of the tracks the will be written in mxf_write_track
    for (i = 0; i < track_count; i++)
        mxf_write_uuid(pb, Track,  mxf->track_instance_count + i);
1640

1641
    // write user comment refs
1642 1643 1644 1645 1646 1647
    if (mxf->store_user_comments) {
        mxf_write_local_tag(pb, user_comment_count*16 + 8, 0x4406);
        mxf_write_refs_count(pb, user_comment_count);
        for (i = 0; i < user_comment_count; i++)
            mxf_write_uuid(pb, TaggedValue, mxf->tagged_value_count - user_comment_count + i);
    }
1648

1649
    // write multiple descriptor reference
1650
    if (package->type == SourcePackage && package->instance == 1) {
1651
        mxf_write_local_tag(pb, 16, 0x4701);
1652 1653 1654 1655 1656
        if (s->nb_streams > 1) {
            mxf_write_uuid(pb, MultipleDescriptor, 0);
            mxf_write_multi_descriptor(s);
        } else
            mxf_write_uuid(pb, SubDescriptor, 0);
1657 1658 1659 1660
    } else if (package->type == SourcePackage && package->instance == 2) {
        mxf_write_local_tag(pb, 16, 0x4701);
        mxf_write_uuid(pb, TapeDescriptor, 0);
        mxf_write_tape_descriptor(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1661
    }
1662

1663 1664 1665 1666 1667 1668 1669 1670
    /*
     * for every 1 track in a package there is 1 sequence and 1 component.
     * all 3 of these elements share the same instance number for generating
     * there instance uuids. mxf->track_instance_count stores this value.
     * mxf->track_instance_count is incremented after a group of all 3 of
     * these elements are written.
     */

1671
    // write timecode track
1672 1673 1674
    mxf_write_track(s, mxf->timecode_track, package);
    mxf_write_sequence(s, mxf->timecode_track, package);
    mxf_write_timecode_component(s, mxf->timecode_track, package);
1675
    mxf->track_instance_count++;
1676

1677
    for (i = 0; i < s->nb_streams; i++) {
1678
        AVStream *st = s->streams[i];
1679 1680 1681
        mxf_write_track(s, st, package);
        mxf_write_sequence(s, st, package);
        mxf_write_structural_component(s, st, package);
1682
        mxf->track_instance_count++;
1683

1684
        if (package->type == SourcePackage && package->instance == 1) {
1685
            MXFStreamContext *sc = st->priv_data;
1686
            mxf_essence_container_uls[sc->index].write_desc(s, st);
1687 1688 1689 1690
        }
    }
}

1691 1692
static int mxf_write_essence_container_data(AVFormatContext *s)
{
1693
    AVIOContext *pb = s->pb;
1694 1695

    mxf_write_metadata_key(pb, 0x012300);
1696
    klv_encode_ber_length(pb, 72);
1697 1698 1699 1700 1701

    mxf_write_local_tag(pb, 16, 0x3C0A); // Instance UID
    mxf_write_uuid(pb, EssenceContainerData, 0);

    mxf_write_local_tag(pb, 32, 0x2701); // Linked Package UID
1702
    mxf_write_umid(s, 1);
1703 1704

    mxf_write_local_tag(pb, 4, 0x3F07); // BodySID
1705
    avio_wb32(pb, 1);
1706

1707
    mxf_write_local_tag(pb, 4, 0x3F06); // IndexSID
1708
    avio_wb32(pb, 2);
1709

1710 1711 1712
    return 0;
}

1713 1714
static int mxf_write_header_metadata_sets(AVFormatContext *s)
{
1715
    MXFContext *mxf = s->priv_data;
1716 1717 1718
    AVDictionaryEntry *entry = NULL;
    AVStream *st = NULL;
    int i;
1719
    MXFPackage packages[3] = {{0}};
1720 1721 1722
    int package_count = 2;
    packages[0].type = MaterialPackage;
    packages[1].type = SourcePackage;
1723
    packages[1].instance = 1;
1724 1725
    packages[0].ref = &packages[1];

1726

1727
    if (entry = av_dict_get(s->metadata, "material_package_name", NULL, 0))
1728
       packages[0].name = entry->value;
1729 1730

    if (entry = av_dict_get(s->metadata, "file_package_name", NULL, 0)) {
1731
        packages[1].name = entry->value;
1732 1733 1734 1735 1736
    } else {
        /* check if any of the streams contain a file_package_name */
        for (i = 0; i < s->nb_streams; i++) {
            st = s->streams[i];
            if (entry = av_dict_get(st->metadata, "file_package_name", NULL, 0)) {
1737
                packages[1].name = entry->value;
1738 1739 1740 1741 1742
                break;
            }
        }
    }

1743 1744 1745 1746 1747 1748 1749 1750 1751
    entry = av_dict_get(s->metadata, "reel_name", NULL, 0);
    if (entry) {
        packages[2].name = entry->value;
        packages[2].type = SourcePackage;
        packages[2].instance = 2;
        packages[1].ref = &packages[2];
        package_count = 3;
    }

1752
    mxf_write_preface(s);
1753
    mxf_write_identification(s);
1754
    mxf_write_content_storage(s, packages, package_count);
1755
    mxf->track_instance_count = 0;
1756 1757
    for (i = 0; i < package_count; i++)
        mxf_write_package(s, &packages[i]);
1758
    mxf_write_essence_container_data(s);
1759 1760 1761
    return 0;
}

1762
static unsigned klv_fill_size(uint64_t size)
1763
{
1764
    unsigned pad = KAG_SIZE - (size & (KAG_SIZE-1));
1765
    if (pad < 20) // smallest fill item possible
1766 1767 1768 1769 1770
        return pad + KAG_SIZE;
    else
        return pad & (KAG_SIZE-1);
}

1771
static void mxf_write_index_table_segment(AVFormatContext *s)
1772 1773
{
    MXFContext *mxf = s->priv_data;
1774
    AVIOContext *pb = s->pb;
1775
    int i, j, temporal_reordering = 0;
1776
    int key_index = mxf->last_key_index;
1777
    int prev_non_b_picture = 0;
1778
    int audio_frame_size = 0;
1779
    int64_t pos;
1780 1781 1782

    av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1783
    if (!mxf->edit_units_count && !mxf->edit_unit_byte_count)
1784 1785
        return;

1786
    avio_write(pb, index_table_segment_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1787

1788 1789
    klv_encode_ber4_length(pb, 0);
    pos = avio_tell(pb);
1790 1791 1792 1793 1794 1795 1796

    // instance id
    mxf_write_local_tag(pb, 16, 0x3C0A);
    mxf_write_uuid(pb, IndexTableSegment, 0);

    // index edit rate
    mxf_write_local_tag(pb, 8, 0x3F0B);
1797 1798
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
1799 1800 1801

    // index start position
    mxf_write_local_tag(pb, 8, 0x3F0C);
1802
    avio_wb64(pb, mxf->last_indexed_edit_unit);
1803 1804 1805

    // index duration
    mxf_write_local_tag(pb, 8, 0x3F0D);
1806
    if (mxf->edit_unit_byte_count)
1807
        avio_wb64(pb, 0); // index table covers whole container
1808
    else
1809
        avio_wb64(pb, mxf->edit_units_count);
1810 1811 1812

    // edit unit byte count
    mxf_write_local_tag(pb, 4, 0x3F05);
1813
    avio_wb32(pb, mxf->edit_unit_byte_count);
1814 1815 1816

    // index sid
    mxf_write_local_tag(pb, 4, 0x3F06);
1817
    avio_wb32(pb, 2);
1818 1819 1820

    // body sid
    mxf_write_local_tag(pb, 4, 0x3F07);
1821
    avio_wb32(pb, 1);
1822

1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847
    // real slice count - 1
    mxf_write_local_tag(pb, 1, 0x3F08);
    avio_w8(pb, !mxf->edit_unit_byte_count); // only one slice for CBR

    // delta entry array
    mxf_write_local_tag(pb, 8 + (s->nb_streams+1)*6, 0x3F09);
    avio_wb32(pb, s->nb_streams+1); // num of entries
    avio_wb32(pb, 6);               // size of one entry
    // write system item delta entry
    avio_w8(pb, 0);
    avio_w8(pb, 0); // slice entry
    avio_wb32(pb, 0); // element delta
    // write each stream delta entry
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MXFStreamContext *sc = st->priv_data;
        avio_w8(pb, sc->temporal_reordering);
        if (sc->temporal_reordering)
            temporal_reordering = 1;
        if (mxf->edit_unit_byte_count) {
            avio_w8(pb, 0); // slice number
            avio_wb32(pb, sc->slice_offset);
        } else if (i == 0) { // video track
            avio_w8(pb, 0); // slice number
            avio_wb32(pb, KAG_SIZE); // system item size including klv fill
1848 1849 1850 1851 1852
        } else { // audio or data track
            if (!audio_frame_size) {
                audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
                audio_frame_size += klv_fill_size(audio_frame_size);
            }
1853 1854
            avio_w8(pb, 1);
            avio_wb32(pb, (i-1)*audio_frame_size); // element delta
1855
        }
1856
    }
1857

1858
    if (!mxf->edit_unit_byte_count) {
1859
        MXFStreamContext *sc = s->streams[0]->priv_data;
1860
        mxf_write_local_tag(pb, 8 + mxf->edit_units_count*15, 0x3F0A);
1861
        avio_wb32(pb, mxf->edit_units_count);  // num of entries
1862
        avio_wb32(pb, 15);  // size of one entry
1863

1864
        for (i = 0; i < mxf->edit_units_count; i++) {
1865
            int temporal_offset = 0;
1866

1867
            if (!(mxf->index_entries[i].flags & 0x33)) { // I-frame
1868
                sc->max_gop = FFMAX(sc->max_gop, i - mxf->last_key_index);
1869 1870 1871 1872
                mxf->last_key_index = key_index;
                key_index = i;
            }

1873
            if (temporal_reordering) {
1874 1875 1876 1877 1878
                int pic_num_in_gop = i - key_index;
                if (pic_num_in_gop != mxf->index_entries[i].temporal_ref) {
                    for (j = key_index; j < mxf->edit_units_count; j++) {
                        if (pic_num_in_gop == mxf->index_entries[j].temporal_ref)
                            break;
1879
                    }
1880 1881 1882
                    if (j == mxf->edit_units_count)
                        av_log(s, AV_LOG_WARNING, "missing frames\n");
                    temporal_offset = j - key_index - pic_num_in_gop;
1883
                }
1884
            }
1885
            avio_w8(pb, temporal_offset);
1886 1887

            if ((mxf->index_entries[i].flags & 0x30) == 0x30) { // back and forward prediction
1888
                sc->b_picture_count = FFMAX(sc->b_picture_count, i - prev_non_b_picture);
1889
                avio_w8(pb, mxf->last_key_index - i);
1890
            } else {
1891
                avio_w8(pb, key_index - i); // key frame offset
1892 1893
                if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward
                    mxf->last_key_index = key_index;
1894
                prev_non_b_picture = i;
1895
            }
1896

1897
            if (!(mxf->index_entries[i].flags & 0x33) && // I-frame
1898 1899
                mxf->index_entries[i].flags & 0x40 && !temporal_offset)
                mxf->index_entries[i].flags |= 0x80; // random access
1900
            avio_w8(pb, mxf->index_entries[i].flags);
1901
            // stream offset
1902
            avio_wb64(pb, mxf->index_entries[i].offset);
1903
            if (s->nb_streams > 1)
1904
                avio_wb32(pb, mxf->index_entries[i].slice_offset);
1905 1906
            else
                avio_wb32(pb, 0);
1907
        }
1908

1909 1910 1911
        mxf->last_key_index = key_index - mxf->edit_units_count;
        mxf->last_indexed_edit_unit += mxf->edit_units_count;
        mxf->edit_units_count = 0;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1912
    }
1913 1914

    mxf_update_klv_size(pb, pos);
1915 1916
}

1917 1918
static void mxf_write_klv_fill(AVFormatContext *s)
{
1919
    unsigned pad = klv_fill_size(avio_tell(s->pb));
1920
    if (pad) {
1921
        avio_write(s->pb, klv_fill_key, 16);
1922 1923
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
1924
        ffio_fill(s->pb, 0, pad);
1925
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
1926 1927 1928
    }
}

1929
static int mxf_write_partition(AVFormatContext *s, int bodysid,
1930
                                int indexsid,
1931
                                const uint8_t *key, int write_metadata)
1932 1933
{
    MXFContext *mxf = s->priv_data;
1934
    AVIOContext *pb = s->pb;
1935
    int64_t header_byte_count_offset;
1936
    unsigned index_byte_count = 0;
1937
    uint64_t partition_offset = avio_tell(pb);
1938
    int err;
1939

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1940 1941
    if (!mxf->edit_unit_byte_count && mxf->edit_units_count)
        index_byte_count = 85 + 12+(s->nb_streams+1)*6 +
1942
            12+mxf->edit_units_count*15;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1943
    else if (mxf->edit_unit_byte_count && indexsid)
1944
        index_byte_count = 80;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1945 1946

    if (index_byte_count) {
1947 1948 1949
        // add encoded ber length
        index_byte_count += 16 + klv_ber_length(index_byte_count);
        index_byte_count += klv_fill_size(index_byte_count);
1950 1951
    }

1952
    if (key && !memcmp(key, body_partition_key, 16)) {
1953 1954 1955 1956 1957
        if ((err = av_reallocp_array(&mxf->body_partition_offset, mxf->body_partitions_count + 1,
                                     sizeof(*mxf->body_partition_offset))) < 0) {
            mxf->body_partitions_count = 0;
            return err;
        }
1958
        mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset;
1959
    }
1960

1961
    // write klv
1962 1963 1964 1965 1966
    if (key)
        avio_write(pb, key, 16);
    else
        avio_write(pb, body_partition_key, 16);

1967
    klv_encode_ber4_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
1968 1969

    // write partition value
1970
    avio_wb16(pb, 1); // majorVersion
1971
    avio_wb16(pb, 3); // minorVersion
1972
    avio_wb32(pb, KAG_SIZE); // KAGSize
1973

1974
    avio_wb64(pb, partition_offset); // ThisPartition
1975

1976
    if (key && !memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
1977
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition
1978
    else if (key && !memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
1979
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
1980
    else
1981
        avio_wb64(pb, 0);
1982

1983
    avio_wb64(pb, mxf->footer_partition_offset); // footerPartition
1984 1985

    // set offset
1986
    header_byte_count_offset = avio_tell(pb);
1987
    avio_wb64(pb, 0); // headerByteCount, update later
1988

1989
    // indexTable
1990 1991
    avio_wb64(pb, index_byte_count); // indexByteCount
    avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
1992 1993

    // BodyOffset
1994
    if (bodysid && mxf->edit_units_count && mxf->body_partitions_count && s->oformat != &ff_mxf_opatom_muxer)
1995
        avio_wb64(pb, mxf->body_offset);
1996
    else
1997
        avio_wb64(pb, 0);
1998

1999
    avio_wb32(pb, bodysid); // bodySID
2000 2001

    // operational pattern
2002 2003 2004 2005
    if (s->oformat == &ff_mxf_opatom_muxer)
        avio_write(pb, opatom_ul, 16);
    else
        avio_write(pb, op1a_ul, 16);
2006 2007

    // essence container
2008
    mxf_write_essence_container_refs(s);
2009 2010 2011

    if (write_metadata) {
        // mark the start of the headermetadata and calculate metadata size
2012
        int64_t pos, start;
2013 2014
        unsigned header_byte_count;

2015
        mxf_write_klv_fill(s);
2016
        start = avio_tell(s->pb);
2017
        mxf_write_primer_pack(s);
2018
        mxf_write_klv_fill(s);
2019
        mxf_write_header_metadata_sets(s);
2020
        pos = avio_tell(s->pb);
2021
        header_byte_count = pos - start + klv_fill_size(pos);
2022

2023
        // update header_byte_count
2024
        avio_seek(pb, header_byte_count_offset, SEEK_SET);
2025
        avio_wb64(pb, header_byte_count);
2026
        avio_seek(pb, pos, SEEK_SET);
2027 2028
    }

2029 2030
    if(key)
        avio_flush(pb);
2031 2032

    return 0;
2033 2034
}

2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071
static const struct {
    int profile;
    UID codec_ul;
} mxf_prores_codec_uls[] = {
    { FF_PROFILE_PRORES_PROXY,    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x01,0x00 } },
    { FF_PROFILE_PRORES_LT,       { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x02,0x00 } },
    { FF_PROFILE_PRORES_STANDARD, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x03,0x00 } },
    { FF_PROFILE_PRORES_HQ,       { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x04,0x00 } },
    { FF_PROFILE_PRORES_4444,     { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x05,0x00 } },
    { FF_PROFILE_PRORES_XQ,       { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x06,0x00 } },
};

static int mxf_parse_prores_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
    MXFStreamContext *sc = st->priv_data;
    int i, profile;

    if (mxf->header_written)
        return 1;

    sc->codec_ul = NULL;
    profile = st->codecpar->profile;
    for (i = 0; i < FF_ARRAY_ELEMS(mxf_prores_codec_uls); i++) {
        if (profile == mxf_prores_codec_uls[i].profile) {
            sc->codec_ul = &mxf_prores_codec_uls[i].codec_ul;
            break;
        }
    }
    if (!sc->codec_ul)
        return 0;

    sc->frame_size = pkt->size;

    return 1;
}

2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098
static const struct {
    int cid;
    UID codec_ul;
} mxf_dnxhd_codec_uls[] = {
    { 1235, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 } }, // 1080p 10bit HIGH
    { 1237, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 } }, // 1080p 8bit MED
    { 1238, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 } }, // 1080p 8bit HIGH
    { 1241, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 } }, // 1080i 10bit HIGH
    { 1242, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 } }, // 1080i 8bit MED
    { 1243, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 } }, // 1080i 8bit HIGH
    { 1244, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x0a,0x00,0x00 } }, // 1080i 8bit TR
    { 1250, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 } }, // 720p 10bit
    { 1251, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 } }, // 720p 8bit HIGH
    { 1252, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 } }, // 720p 8bit MED
    { 1253, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 } }, // 720p 8bit LOW
    { 1256, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x16,0x00,0x00 } }, // 1080p 10bit 444
    { 1258, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x18,0x00,0x00 } }, // 720p 8bit TR
    { 1259, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x19,0x00,0x00 } }, // 1080p 8bit TR
    { 1260, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x1a,0x00,0x00 } }, // 1080i 8bit TR MBAFF
    { 1270, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 } }, // DNXHR 444
    { 1271, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 } }, // DNXHR HQX
    { 1272, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 } }, // DNXHR HQ
    { 1273, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 } }, // DNXHR SQ
    { 1274, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 } }, // DNXHR LB
};

static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
2099 2100 2101
{
    MXFContext *mxf = s->priv_data;
    MXFStreamContext *sc = st->priv_data;
2102
    int i, cid, frame_size = 0;
2103 2104 2105 2106 2107

    if (mxf->header_written)
        return 1;

    if (pkt->size < 43)
2108
        return 0;
2109

2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128
    sc->codec_ul = NULL;
    cid = AV_RB32(pkt->data + 0x28);
    for (i = 0; i < FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls); i++) {
        if (cid == mxf_dnxhd_codec_uls[i].cid) {
            sc->codec_ul = &mxf_dnxhd_codec_uls[i].codec_ul;
            break;
        }
    }
    if (!sc->codec_ul)
        return 0;

    sc->component_depth = 0;
    switch (pkt->data[0x21] >> 5) {
    case 1: sc->component_depth = 8; break;
    case 2: sc->component_depth = 10; break;
    case 3: sc->component_depth = 12; break;
    }
    if (!sc->component_depth)
        return 0;
2129

2130 2131 2132 2133
    if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) == DNXHD_VARIABLE) {
        frame_size = avpriv_dnxhd_get_hr_frame_size(cid, st->codecpar->width, st->codecpar->height);
    }
    if (frame_size < 0)
2134 2135
        return 0;

2136
    if ((sc->interlaced = avpriv_dnxhd_get_interlaced(cid)) < 0)
2137
        return 0;
2138

2139 2140 2141 2142 2143 2144
    if (cid >= 1270) { // RI raster
        av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
                  st->codecpar->width, st->codecpar->height,
                  INT_MAX);
    } else {
        sc->aspect_ratio = (AVRational){ 16, 9 };
2145 2146
    }

2147
    sc->frame_size = pkt->size;
2148 2149 2150 2151

    return 1;
}

2152 2153 2154 2155 2156
static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
    MXFStreamContext *sc = st->priv_data;
    uint8_t *vs_pack, *vsc_pack;
2157
    int ul_index, stype, pal;
2158
    const AVDVProfile *profile;
2159 2160 2161 2162 2163 2164 2165 2166

    if (mxf->header_written)
        return 1;

    // Check for minimal frame size
    if (pkt->size < 120000)
        return -1;

2167 2168
    profile = av_dv_frame_profile(NULL, pkt->data, pkt->size);

2169 2170 2171 2172 2173
    vs_pack  = pkt->data + 80*5 + 48;
    vsc_pack = pkt->data + 80*5 + 53;
    stype    = vs_pack[3] & 0x1f;
    pal      = (vs_pack[3] >> 5) & 0x1;

2174
    if ((vsc_pack[2] & 0x07) == 0x02) {
2175
        sc->aspect_ratio = (AVRational){ 16, 9 };
2176
    } else {
2177
        sc->aspect_ratio = (AVRational){ 4, 3 };
2178
    }
2179 2180 2181 2182 2183 2184 2185 2186

    sc->interlaced = (vsc_pack[3] >> 4) & 0x01;
    // TODO: fix dv encoder to set proper FF/FS value in VSC pack
    // and set field dominance accordingly
    // av_log(s, AV_LOG_DEBUG, "DV vsc pack ff/ss = %x\n", vsc_pack[2] >> 6);

    switch (stype) {
    case 0x18: // DV100 720p
2187
        ul_index = INDEX_DV100_720_50 + pal;
2188
        if (sc->interlaced) {
2189
            av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n");
2190 2191 2192 2193
            sc->interlaced = 0;
        }
        break;
    case 0x14: // DV100 1080i
2194
        ul_index = INDEX_DV100_1080_50 + pal;
2195 2196
        break;
    case 0x04: // DV50
2197
        ul_index = INDEX_DV50_525_60 + pal;
2198 2199
        break;
    default: // DV25
2200 2201 2202 2203
        if (profile && profile->pix_fmt == AV_PIX_FMT_YUV420P && pal) {
            ul_index = INDEX_DV25_525_60_IEC + pal;
            break;
        }
2204
        ul_index = INDEX_DV25_525_60 + pal;
2205 2206
    }

2207
    sc->index = ul_index;
2208
    sc->codec_ul =  &mxf_essence_container_uls[sc->index].codec_ul;
2209
    sc->frame_size = pkt->size;
2210 2211 2212 2213

    return 1;
}

2214 2215 2216 2217 2218
static const struct {
    UID uid;
    int frame_size;
    int profile;
    uint8_t interlaced;
2219
    int intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored
2220
} mxf_h264_codec_uls[] = {
2221
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 },      0,  66, 0, -1 }, // AVC Baseline
2222 2223 2224
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x20,0x01 },      0,  77, 0, -1 }, // AVC Main
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x30,0x01 },      0,  88, 0, -1 }, // AVC Extended
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x40,0x01 },      0, 100, 0, -1 }, // AVC High
2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01 },      0, 110, 0,  0 }, // AVC High 10
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01 },      0, 122, 0,  0 }, // AVC High 422
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01 },      0, 244, 0,  0 }, // AVC High 444
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 },      0, 110, 0,  1 }, // AVC High 10 Intra
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960, 110, 1,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/59.94i
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088, 110, 1,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/50i
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/29.97p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 281088, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/25p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 720/59.94p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, 140800, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 720/50p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 },      0, 122, 0,  1 }, // AVC High 422 Intra
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576, 122, 1,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/59.94i
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832, 122, 1,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/50i
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/29.97p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, 568832, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/25p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 720/59.94p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, 284672, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 720/50p
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01 },      0, 244, 0,  1 }, // AVC High 444 Intra
2243
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x50,0x01 },      0,  44, 0, -1 }, // AVC CAVLC 444
2244 2245 2246 2247 2248 2249 2250
};

static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
                                AVPacket *pkt, MXFIndexEntry *e)
{
    MXFContext *mxf = s->priv_data;
    MXFStreamContext *sc = st->priv_data;
2251 2252
    H264SequenceParameterSet *sps = NULL;
    GetBitContext gb;
2253 2254
    const uint8_t *buf = pkt->data;
    const uint8_t *buf_end = pkt->data + pkt->size;
2255
    const uint8_t *nal_end;
2256 2257
    uint32_t state = -1;
    int extra_size = 512; // support AVC Intra files without SPS/PPS header
2258
    int i, frame_size, slice_type, intra_only = 0;
2259 2260 2261 2262 2263

    for (;;) {
        buf = avpriv_find_start_code(buf, buf_end, &state);
        if (buf >= buf_end)
            break;
2264

2265
        switch (state & 0x1f) {
James Almer's avatar
James Almer committed
2266
        case H264_NAL_SPS:
2267
            e->flags |= 0x40;
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287

            if (mxf->header_written)
                break;

            nal_end = ff_avc_find_startcode(buf, buf_end);
            sps = ff_avc_decode_sps(buf, nal_end - buf);
            if (!sps) {
                av_log(s, AV_LOG_ERROR, "error parsing sps\n");
                return 0;
            }

            sc->aspect_ratio.num = st->codecpar->width * sps->sar.num;
            sc->aspect_ratio.den = st->codecpar->height * sps->sar.den;
            av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
                      sc->aspect_ratio.num, sc->aspect_ratio.den, 1024*1024);
            intra_only = (sps->constraint_set_flags >> 3) & 1;
            sc->interlaced = !sps->frame_mbs_only_flag;
            sc->component_depth = sps->bit_depth_luma;

            buf = nal_end;
2288
            break;
James Almer's avatar
James Almer committed
2289
        case H264_NAL_PPS:
2290 2291 2292 2293 2294
            if (e->flags & 0x40) { // sequence header present
                e->flags |= 0x80; // random access
                extra_size = 0;
            }
            break;
2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314
        case H264_NAL_IDR_SLICE:
            e->flags |= 0x04; // IDR Picture
            buf = buf_end;
            break;
        case H264_NAL_SLICE:
            init_get_bits8(&gb, buf, buf_end - buf);
            get_ue_golomb_long(&gb); // skip first_mb_in_slice
            slice_type = get_ue_golomb_31(&gb);
            switch (slice_type % 5) {
            case 0:
                e->flags |= 0x20; // P Picture
                e->flags |= 0x06; // P Picture
                break;
            case 1:
                e->flags |= 0x30; // B Picture
                e->flags |= 0x03; // non-referenced B Picture
                break;
            }
            buf = buf_end;
            break;
2315 2316 2317 2318 2319 2320 2321 2322
        default:
            break;
        }
    }

    if (mxf->header_written)
        return 1;

2323 2324 2325
    if (!sps)
        sc->interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
    sc->codec_ul = NULL;
2326
    frame_size = pkt->size + extra_size;
2327 2328

    for (i = 0; i < FF_ARRAY_ELEMS(mxf_h264_codec_uls); i++) {
2329 2330
        if (frame_size == mxf_h264_codec_uls[i].frame_size && sc->interlaced == mxf_h264_codec_uls[i].interlaced) {
            sc->codec_ul = &mxf_h264_codec_uls[i].uid;
2331
            sc->component_depth = 10; // AVC Intra is always 10 Bit
2332 2333 2334 2335 2336
            sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
            st->codecpar->profile = mxf_h264_codec_uls[i].profile;
            sc->avc_intra = 1;
            mxf->cbr_index = 1;
            sc->frame_size = pkt->size;
2337 2338
            if (sc->interlaced)
                sc->field_dominance = 1; // top field first is mandatory for AVC Intra
2339 2340 2341 2342 2343
            break;
        } else if (sps && mxf_h264_codec_uls[i].frame_size == 0 &&
                   mxf_h264_codec_uls[i].profile == sps->profile_idc &&
                   (mxf_h264_codec_uls[i].intra_only < 0 ||
                    mxf_h264_codec_uls[i].intra_only == intra_only)) {
2344
            sc->codec_ul = &mxf_h264_codec_uls[i].uid;
2345 2346 2347
            st->codecpar->profile = sps->profile_idc;
            st->codecpar->level = sps->level_idc;
            // continue to check for avc intra
2348 2349 2350
        }
    }

2351 2352 2353
    av_free(sps);

    if (!sc->codec_ul) {
2354
        av_log(s, AV_LOG_ERROR, "h264 profile not supported\n");
2355 2356 2357 2358 2359 2360
        return 0;
    }

    return 1;
}

2361 2362 2363 2364 2365 2366 2367 2368 2369
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
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x02,0x00 }, // 422P-ML I-Frame
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x03,0x00 }, // 422P-ML Long GOP
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x02,0x00 }, // MP-HL I-Frame
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, // MP-HL Long GOP
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, // 422P-HL I-Frame
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, // 422P-HL Long GOP
2370 2371
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x05,0x02,0x00 }, // MP@H-14 I-Frame
    { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x05,0x03,0x00 }, // MP@H-14 Long GOP
2372 2373
};

2374
static const UID *mxf_get_mpeg2_codec_ul(AVCodecParameters *par)
2375
{
2376
    int long_gop = 1;
2377

2378 2379
    if (par->profile == 4) { // Main
        if (par->level == 8) // Main
2380
            return &mxf_mpeg2_codec_uls[0+long_gop];
2381
        else if (par->level == 4) // High
2382
            return &mxf_mpeg2_codec_uls[4+long_gop];
2383
        else if (par->level == 6) // High 14
2384
            return &mxf_mpeg2_codec_uls[8+long_gop];
2385 2386
    } else if (par->profile == 0) { // 422
        if (par->level == 5) // Main
2387
            return &mxf_mpeg2_codec_uls[2+long_gop];
2388
        else if (par->level == 2) // High
2389
            return &mxf_mpeg2_codec_uls[6+long_gop];
2390 2391 2392 2393
    }
    return NULL;
}

2394 2395
static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
                                 AVPacket *pkt, MXFIndexEntry *e)
2396 2397 2398 2399 2400 2401 2402
{
    MXFStreamContext *sc = st->priv_data;
    uint32_t c = -1;
    int i;

    for(i = 0; i < pkt->size - 4; i++) {
        c = (c<<8) + pkt->data[i];
2403
        if (c == 0x1b5) {
2404
            if ((pkt->data[i+1] & 0xf0) == 0x10) { // seq ext
2405 2406
                st->codecpar->profile = pkt->data[i+1] & 0x07;
                st->codecpar->level   = pkt->data[i+2] >> 4;
2407
                sc->low_delay = pkt->data[i+6] >> 7;
2408 2409
            } else if (i + 5 < pkt->size && (pkt->data[i+1] & 0xf0) == 0x80) { // pict coding ext
                sc->interlaced = !(pkt->data[i+5] & 0x80); // progressive frame
2410 2411
                if (sc->interlaced)
                    sc->field_dominance = 1 + !(pkt->data[i+4] & 0x80); // top field first
2412 2413
                break;
            }
2414
        } else if (c == 0x1b8) { // gop
2415
            if (pkt->data[i+4]>>6 & 0x01) { // closed
2416 2417
                if (sc->seq_closed_gop == -1)
                    sc->seq_closed_gop = 1;
2418
                sc->closed_gop = 1;
2419 2420
                if (e->flags & 0x40) // sequence header present
                    e->flags |= 0x80; // random access
2421 2422 2423
            } else {
                sc->seq_closed_gop = 0;
                sc->closed_gop = 0;
2424
            }
2425
        } else if (c == 0x1b3) { // seq
2426
            e->flags |= 0x40;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2427 2428 2429 2430 2431 2432
            switch ((pkt->data[i+4]>>4) & 0xf) {
            case 2:  sc->aspect_ratio = (AVRational){  4,  3}; break;
            case 3:  sc->aspect_ratio = (AVRational){ 16,  9}; break;
            case 4:  sc->aspect_ratio = (AVRational){221,100}; break;
            default:
                av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
2433
                          st->codecpar->width, st->codecpar->height, 1024*1024);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2434
            }
2435 2436
        } else if (c == 0x100) { // pic
            int pict_type = (pkt->data[i+2]>>3) & 0x07;
2437
            e->temporal_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
2438
            if (pict_type == 2) { // P-frame
2439
                e->flags |= 0x22;
2440 2441
                sc->closed_gop = 0; // reset closed GOP, don't matter anymore
            } else if (pict_type == 3) { // B-frame
2442
                if (sc->closed_gop)
2443
                    e->flags |= 0x13; // only backward prediction
2444
                else
2445
                    e->flags |= 0x33;
2446 2447 2448 2449 2450
                sc->temporal_reordering = -1;
            } else if (!pict_type) {
                av_log(s, AV_LOG_ERROR, "error parsing mpeg2 frame\n");
                return 0;
            }
2451 2452
        }
    }
2453
    if (s->oformat != &ff_mxf_d10_muxer)
2454
        sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar);
2455 2456 2457
    return !!sc->codec_ul;
}

2458
static uint64_t mxf_parse_timestamp(int64_t timestamp64)
2459
{
2460
    time_t timestamp = timestamp64 / 1000000;
2461 2462
    struct tm tmbuf;
    struct tm *time = gmtime_r(&timestamp, &tmbuf);
2463 2464
    if (!time)
        return 0;
2465 2466 2467 2468 2469
    return (uint64_t)(time->tm_year+1900) << 48 |
           (uint64_t)(time->tm_mon+1)     << 40 |
           (uint64_t) time->tm_mday       << 32 |
                      time->tm_hour       << 24 |
                      time->tm_min        << 16 |
2470 2471
                      time->tm_sec        << 8  |
                      (timestamp64 % 1000000) / 4000;
2472 2473
}

2474 2475 2476
static void mxf_gen_umid(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2477
    uint32_t seed = av_get_random_seed();
2478 2479 2480 2481 2482
    uint64_t umid = seed + 0x5294713400000000LL;

    AV_WB64(mxf->umid  , umid);
    AV_WB64(mxf->umid+8, umid>>8);

2483
    mxf->instance_number = seed & 0xFFFFFF;
2484 2485
}

2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498
static int mxf_init_timecode(AVFormatContext *s, AVStream *st, AVRational rate)
{
    MXFContext *mxf = s->priv_data;
    AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
    if (!tcr)
        tcr = av_dict_get(st->metadata, "timecode", NULL, 0);

    if (tcr)
        return av_timecode_init_from_string(&mxf->tc, rate, tcr->value, s);
    else
        return av_timecode_init(&mxf->tc, rate, 0, 0, s);
}

2499
static int mxf_write_header(AVFormatContext *s)
2500 2501
{
    MXFContext *mxf = s->priv_data;
2502
    int i, ret;
2503
    uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
2504
    const MXFSamplesPerFrame *spf = NULL;
2505
    int64_t timestamp = 0;
2506

2507 2508 2509
    if (!s->nb_streams)
        return -1;

2510
    if (s->oformat == &ff_mxf_opatom_muxer && s->nb_streams !=1) {
2511 2512 2513 2514
        av_log(s, AV_LOG_ERROR, "there must be exactly one stream for mxf opatom\n");
        return -1;
    }

2515 2516 2517
    if (!av_dict_get(s->metadata, "comment_", NULL, AV_DICT_IGNORE_SUFFIX))
        mxf->store_user_comments = 0;

2518 2519
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
2520
        MXFStreamContext *sc = av_mallocz(sizeof(*sc));
2521 2522 2523
        if (!sc)
            return AVERROR(ENOMEM);
        st->priv_data = sc;
2524

2525
        if (((i == 0) ^ (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) && s->oformat != &ff_mxf_opatom_muxer) {
2526 2527 2528 2529
            av_log(s, AV_LOG_ERROR, "there must be exactly one video stream and it must be the first one\n");
            return -1;
        }

2530
        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
2531
            const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(st->codecpar->format);
2532
            // TODO: should be avg_frame_rate
2533
            AVRational rate, tbc = st->time_base;
2534 2535
            // Default component depth to 8
            sc->component_depth = 8;
2536
            sc->h_chroma_sub_sample = 2;
2537
            sc->v_chroma_sub_sample = 2;
2538
            sc->color_siting = 0xFF;
2539

2540 2541 2542 2543 2544
            if (st->codecpar->sample_aspect_ratio.num && st->codecpar->sample_aspect_ratio.den) {
                sc->aspect_ratio = av_mul_q(st->codecpar->sample_aspect_ratio,
                                            av_make_q(st->codecpar->width, st->codecpar->height));
            }

2545
            if (pix_desc) {
2546
                sc->component_depth     = pix_desc->comp[0].depth;
2547
                sc->h_chroma_sub_sample = 1 << pix_desc->log2_chroma_w;
2548
                sc->v_chroma_sub_sample = 1 << pix_desc->log2_chroma_h;
2549
            }
2550 2551 2552 2553 2554 2555
            switch (ff_choose_chroma_location(s, st)) {
            case AVCHROMA_LOC_TOPLEFT: sc->color_siting = 0; break;
            case AVCHROMA_LOC_LEFT:    sc->color_siting = 6; break;
            case AVCHROMA_LOC_TOP:     sc->color_siting = 1; break;
            case AVCHROMA_LOC_CENTER:  sc->color_siting = 3; break;
            }
2556

2557
            mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num;
2558
            spf = ff_mxf_get_samples_per_frame(s, tbc);
2559
            if (!spf) {
2560 2561 2562
                av_log(s, AV_LOG_ERROR, "Unsupported video frame rate %d/%d\n",
                       tbc.den, tbc.num);
                return AVERROR(EINVAL);
2563
            }
2564
            mxf->content_package_rate = ff_mxf_get_content_package_rate(tbc);
2565
            mxf->time_base = spf->time_base;
2566
            rate = av_inv_q(mxf->time_base);
2567
            avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
2568
            if((ret = mxf_init_timecode(s, st, rate)) < 0)
2569
                return ret;
2570

2571 2572 2573 2574
            if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
                sc->seq_closed_gop = -1; // unknown yet
            }

2575
            sc->video_bit_rate = st->codecpar->bit_rate;
2576 2577 2578 2579 2580 2581

            if (s->oformat == &ff_mxf_d10_muxer ||
                st->codecpar->codec_id == AV_CODEC_ID_DNXHD ||
                st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO)
                mxf->cbr_index = 1;

2582
            if (s->oformat == &ff_mxf_d10_muxer) {
2583 2584 2585 2586
                if (st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO) {
                    av_log(s, AV_LOG_ERROR, "error MXF D-10 only support MPEG-2 Video\n");
                    return AVERROR(EINVAL);
                }
2587
                if ((sc->video_bit_rate == 50000000) && (mxf->time_base.den == 25)) {
2588
                    sc->index = INDEX_D10_625_50_50_VIDEO;
2589
                } else if ((sc->video_bit_rate == 49999840 || sc->video_bit_rate == 50000000) && (mxf->time_base.den != 25)) {
2590
                    sc->index = INDEX_D10_525_60_50_VIDEO;
2591
                } else if (sc->video_bit_rate == 40000000) {
2592 2593
                    if (mxf->time_base.den == 25) sc->index = INDEX_D10_625_50_40_VIDEO;
                    else                          sc->index = INDEX_D10_525_60_40_VIDEO;
2594
                } else if (sc->video_bit_rate == 30000000) {
2595 2596
                    if (mxf->time_base.den == 25) sc->index = INDEX_D10_625_50_30_VIDEO;
                    else                          sc->index = INDEX_D10_525_60_30_VIDEO;
2597
                } else {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2598 2599 2600 2601
                    av_log(s, AV_LOG_ERROR, "error MXF D-10 only support 30/40/50 mbit/s\n");
                    return -1;
                }

2602
                sc->signal_standard = 1;
2603
                sc->color_siting = 0;
2604 2605
                sc->frame_size = (int64_t)sc->video_bit_rate *
                    mxf->time_base.num / (8*mxf->time_base.den);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2606
            }
2607 2608
            if (mxf->signal_standard >= 0)
                sc->signal_standard = mxf->signal_standard;
2609 2610
        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            if (st->codecpar->sample_rate != 48000) {
2611 2612 2613
                av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
                return -1;
            }
2614
            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
2615
            if (s->oformat == &ff_mxf_d10_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2616 2617 2618 2619
                if (st->index != 1) {
                    av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n");
                    return -1;
                }
2620 2621
                if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE &&
                    st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2622 2623 2624
                    av_log(s, AV_LOG_ERROR, "MXF D-10 only support 16 or 24 bits le audio\n");
                }
                sc->index = ((MXFStreamContext*)s->streams[0]->priv_data)->index + 1;
2625
                sc->frame_size = 4 + 8 * spf[0].samples_per_frame[0] * 4;
2626 2627 2628
            } else if (s->oformat == &ff_mxf_opatom_muxer) {
                AVRational tbc = av_inv_q(mxf->audio_edit_rate);

2629 2630
                if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE &&
                    st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) {
2631 2632 2633
                    av_log(s, AV_LOG_ERROR, "Only pcm_s16le and pcm_s24le audio codecs are implemented\n");
                    return AVERROR_PATCHWELCOME;
                }
2634
                if (st->codecpar->channels != 1) {
2635 2636 2637 2638 2639
                    av_log(s, AV_LOG_ERROR, "MXF OPAtom only supports single channel audio\n");
                    return AVERROR(EINVAL);
                }

                spf = ff_mxf_get_samples_per_frame(s, tbc);
2640
                if (!spf) {
2641 2642 2643 2644 2645 2646 2647 2648 2649
                    av_log(s, AV_LOG_ERROR, "Unsupported timecode frame rate %d/%d\n", tbc.den, tbc.num);
                    return AVERROR(EINVAL);
                }

                mxf->time_base = st->time_base;
                if((ret = mxf_init_timecode(s, st, av_inv_q(spf->time_base))) < 0)
                    return ret;

                mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num;
2650
                mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3;
2651
                sc->index = INDEX_WAV;
2652 2653
            } else {
                mxf->slice_count = 1;
2654 2655
                sc->frame_size = (st->codecpar->channels * spf[0].samples_per_frame[0] *
                                  av_get_bits_per_sample(st->codecpar->codec_id)) / 8;
2656
            }
2657 2658 2659
        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
            AVDictionaryEntry *e = av_dict_get(st->metadata, "data_type", NULL, 0);
            if (e && !strcmp(e->value, "vbi_vanc_smpte_436M")) {
2660
                sc->index = INDEX_S436M;
2661 2662 2663 2664 2665 2666 2667 2668
            } else {
                av_log(s, AV_LOG_ERROR, "track %d: unsupported data type\n", i);
                return -1;
            }
            if (st->index != s->nb_streams - 1) {
                av_log(s, AV_LOG_ERROR, "data track must be placed last\n");
                return -1;
            }
2669
        }
2670

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2671
        if (!sc->index) {
2672
            sc->index = mxf_get_essence_container_ul_index(st->codecpar->codec_id);
2673 2674 2675 2676 2677
            if (sc->index == -1) {
                av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, "
                       "codec not currently supported in container\n", i);
                return -1;
            }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2678
        }
2679

2680
        sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
2681

2682 2683
        memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15);
        sc->track_essence_element_key[15] = present[sc->index];
2684
        PRINT_KEY(s, "track essence element key", sc->track_essence_element_key);
2685 2686 2687 2688

        if (!present[sc->index])
            mxf->essence_container_count++;
        present[sc->index]++;
2689
    }
2690

2691
    if (s->oformat == &ff_mxf_d10_muxer || s->oformat == &ff_mxf_opatom_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2692 2693 2694
        mxf->essence_container_count = 1;
    }

2695
    if (!(s->flags & AVFMT_FLAG_BITEXACT))
2696 2697
        mxf_gen_umid(s);

2698 2699 2700 2701
    for (i = 0; i < s->nb_streams; i++) {
        MXFStreamContext *sc = s->streams[i]->priv_data;
        // update element count
        sc->track_essence_element_key[13] = present[sc->index];
2702 2703 2704 2705
        if (!memcmp(sc->track_essence_element_key, mxf_essence_container_uls[15].element_ul, 13)) // DV
            sc->order = (0x15 << 24) | AV_RB32(sc->track_essence_element_key+13);
        else
            sc->order = AV_RB32(sc->track_essence_element_key+12);
2706 2707
    }

2708
    if (ff_parse_creation_time_metadata(s, &timestamp, 0) > 0)
2709
        mxf->timestamp = mxf_parse_timestamp(timestamp);
2710 2711 2712 2713 2714 2715 2716 2717
    mxf->duration = -1;

    mxf->timecode_track = av_mallocz(sizeof(*mxf->timecode_track));
    if (!mxf->timecode_track)
        return AVERROR(ENOMEM);
    mxf->timecode_track->priv_data = av_mallocz(sizeof(MXFStreamContext));
    if (!mxf->timecode_track->priv_data)
        return AVERROR(ENOMEM);
2718
    mxf->timecode_track->index = -1;
2719

2720
    if (!spf)
2721
        spf = ff_mxf_get_samples_per_frame(s, (AVRational){ 1, 25 });
2722

2723
    if (ff_audio_interleave_init(s, spf->samples_per_frame, mxf->time_base) < 0)
2724 2725
        return -1;

2726 2727 2728
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2729 2730 2731 2732 2733 2734
static const uint8_t system_metadata_pack_key[]        = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x03,0x01,0x04,0x01,0x01,0x00 };
static const uint8_t system_metadata_package_set_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x43,0x01,0x01,0x0D,0x01,0x03,0x01,0x04,0x01,0x02,0x01 };

static void mxf_write_system_item(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2735
    AVIOContext *pb = s->pb;
2736
    unsigned frame;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2737
    uint32_t time_code;
2738
    int i, system_item_bitmap = 0x58; // UL, user date/time stamp, picture present
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2739

2740
    frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2741 2742

    // write system metadata pack
2743
    avio_write(pb, system_metadata_pack_key, 16);
2744
    klv_encode_ber4_length(pb, 57);
2745 2746 2747 2748 2749 2750 2751 2752

    for (i = 0; i < s->nb_streams; i++) {
        if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
            system_item_bitmap |= 0x4;
        else if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_DATA)
            system_item_bitmap |= 0x2;
    }
    avio_w8(pb, system_item_bitmap);
2753
    avio_w8(pb, mxf->content_package_rate); // content package rate
2754 2755
    avio_w8(pb, 0x00); // content package type
    avio_wb16(pb, 0x00); // channel handle
2756
    avio_wb16(pb, (mxf->tc.start + frame) & 0xFFFF); // continuity count, supposed to overflow
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2757
    if (mxf->essence_container_count > 1)
2758
        avio_write(pb, multiple_desc_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2759 2760
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
2761
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2762
    }
2763 2764 2765
    avio_w8(pb, 0);
    avio_wb64(pb, 0);
    avio_wb64(pb, 0); // creation date/time stamp
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2766

2767
    avio_w8(pb, 0x81); // SMPTE 12M time code
2768
    time_code = av_timecode_get_smpte_from_framenum(&mxf->tc, frame);
2769 2770 2771
    avio_wb32(pb, time_code);
    avio_wb32(pb, 0); // binary group data
    avio_wb64(pb, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2772 2773

    // write system metadata package set
2774
    avio_write(pb, system_metadata_package_set_key, 16);
2775
    klv_encode_ber4_length(pb, 35);
2776 2777
    avio_w8(pb, 0x83); // UMID
    avio_wb16(pb, 0x20);
2778
    mxf_write_umid(s, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2779 2780
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2781 2782 2783
static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
2784
    AVIOContext *pb = s->pb;
2785
    int frame_size = pkt->size / st->codecpar->block_align;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2786 2787 2788 2789 2790 2791
    uint8_t *samples = pkt->data;
    uint8_t *end = pkt->data + pkt->size;
    int i;

    klv_encode_ber4_length(pb, 4 + frame_size*4*8);

2792 2793
    avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1));
    avio_wl16(pb, frame_size);
2794
    avio_w8(pb, (1<<st->codecpar->channels)-1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2795 2796

    while (samples < end) {
2797
        for (i = 0; i < st->codecpar->channels; i++) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2798
            uint32_t sample;
2799
            if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
2800
                sample = AV_RL24(samples)<< 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2801 2802
                samples += 3;
            } else {
2803
                sample = AV_RL16(samples)<<12;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2804 2805
                samples += 2;
            }
2806
            avio_wl32(pb, sample | i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2807 2808
        }
        for (; i < 8; i++)
2809
            avio_wl32(pb, i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2810 2811 2812
    }
}

2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863
static int mxf_write_opatom_body_partition(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
    AVIOContext *pb = s->pb;
    AVStream *st = s->streams[0];
    MXFStreamContext *sc = st->priv_data;
    const uint8_t *key = NULL;

    int err;

    if (!mxf->header_written)
        key = body_partition_key;

    if ((err = mxf_write_partition(s, 1, 0, key, 0)) < 0)
        return err;
    mxf_write_klv_fill(s);
    avio_write(pb, sc->track_essence_element_key, 16);
    klv_encode_ber9_length(pb, mxf->body_offset);
    return 0;
}

static int mxf_write_opatom_packet(AVFormatContext *s, AVPacket *pkt, MXFIndexEntry *ie)
{
    MXFContext *mxf = s->priv_data;
    AVIOContext *pb = s->pb;

    int err;

    if (!mxf->header_written) {
        if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0)
            return err;
        mxf_write_klv_fill(s);

        if ((err = mxf_write_opatom_body_partition(s)) < 0)
            return err;
        mxf->header_written = 1;
    }

    if (!mxf->edit_unit_byte_count) {
        mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
        mxf->index_entries[mxf->edit_units_count].flags = ie->flags;
        mxf->index_entries[mxf->edit_units_count].temporal_ref = ie->temporal_ref;
    }
    mxf->edit_units_count++;
    avio_write(pb, pkt->data, pkt->size);
    mxf->body_offset += pkt->size;
    avio_flush(pb);

    return 0;
}

2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884
static void mxf_compute_edit_unit_byte_count(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
    int i;

    if (s->oformat == &ff_mxf_opatom_muxer) {
        MXFStreamContext *sc = s->streams[0]->priv_data;
        mxf->edit_unit_byte_count = sc->frame_size;
        return;
    }

    mxf->edit_unit_byte_count = KAG_SIZE; // system element
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MXFStreamContext *sc = st->priv_data;
        sc->slice_offset = mxf->edit_unit_byte_count;
        mxf->edit_unit_byte_count += 16 + 4 + sc->frame_size;
        mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
    }
}

2885
static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
2886
{
2887
    MXFContext *mxf = s->priv_data;
2888
    AVIOContext *pb = s->pb;
2889 2890
    AVStream *st = s->streams[pkt->stream_index];
    MXFStreamContext *sc = st->priv_data;
2891
    MXFIndexEntry ie = {0};
2892
    int err;
2893

2894
    if (!mxf->cbr_index && !mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) {
2895 2896 2897
        if ((err = av_reallocp_array(&mxf->index_entries, mxf->edit_units_count
                                     + EDIT_UNITS_PER_BODY, sizeof(*mxf->index_entries))) < 0) {
            mxf->edit_units_count = 0;
2898
            av_log(s, AV_LOG_ERROR, "could not allocate index entries\n");
2899
            return err;
2900 2901 2902
        }
    }

2903
    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
2904
        if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
2905 2906
            av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
            return -1;
2907
        }
2908
    } else if (st->codecpar->codec_id == AV_CODEC_ID_DNXHD) {
2909 2910 2911 2912
        if (!mxf_parse_dnxhd_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
            return -1;
        }
2913 2914 2915 2916 2917
    } else if (st->codecpar->codec_id == AV_CODEC_ID_PRORES) {
        if (!mxf_parse_prores_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get prores profile\n");
            return -1;
        }
2918
    } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
2919 2920 2921 2922
        if (!mxf_parse_dv_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
            return -1;
        }
2923
    } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
2924 2925 2926 2927
        if (!mxf_parse_h264_frame(s, st, pkt, &ie)) {
            av_log(s, AV_LOG_ERROR, "could not get h264 profile\n");
            return -1;
        }
2928 2929
    }

2930 2931 2932 2933 2934 2935 2936 2937 2938 2939
    if (mxf->cbr_index) {
        if (pkt->size != sc->frame_size && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            av_log(s, AV_LOG_ERROR, "track %d: frame size does not match index unit size, %d != %d\n",
                   st->index, pkt->size, sc->frame_size);
            return -1;
        }
        if (!mxf->header_written)
            mxf_compute_edit_unit_byte_count(s);
    }

2940 2941 2942
    if (s->oformat == &ff_mxf_opatom_muxer)
        return mxf_write_opatom_packet(s, pkt, &ie);

2943
    if (!mxf->header_written) {
2944
        if (mxf->edit_unit_byte_count) {
2945 2946
            if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0)
                return err;
2947 2948 2949
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        } else {
2950 2951
            if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0)
                return err;
2952
        }
2953 2954 2955
        mxf->header_written = 1;
    }

2956
    if (st->index == 0) {
2957 2958
        if (!mxf->edit_unit_byte_count &&
            (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) &&
2959
            !(ie.flags & 0x33)) { // I-frame, GOP start
2960
            mxf_write_klv_fill(s);
2961 2962
            if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0)
                return err;
2963 2964 2965 2966
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2967
        mxf_write_klv_fill(s);
2968
        mxf_write_system_item(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2969

2970 2971
        if (!mxf->edit_unit_byte_count) {
            mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
2972 2973
            mxf->index_entries[mxf->edit_units_count].flags = ie.flags;
            mxf->index_entries[mxf->edit_units_count].temporal_ref = ie.temporal_ref;
2974 2975
            mxf->body_offset += KAG_SIZE; // size of system element
        }
2976
        mxf->edit_units_count++;
2977
    } else if (!mxf->edit_unit_byte_count && st->index == 1) {
2978 2979 2980 2981
        if (!mxf->edit_units_count) {
            av_log(s, AV_LOG_ERROR, "No packets in first stream\n");
            return AVERROR_PATCHWELCOME;
        }
2982 2983
        mxf->index_entries[mxf->edit_units_count-1].slice_offset =
            mxf->body_offset - mxf->index_entries[mxf->edit_units_count-1].offset;
2984 2985
    }

2986
    mxf_write_klv_fill(s);
2987
    avio_write(pb, sc->track_essence_element_key, 16); // write key
2988 2989 2990
    if (s->oformat == &ff_mxf_d10_muxer &&
        st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
        mxf_write_d10_audio_packet(s, st, pkt);
2991 2992
    } else {
        klv_encode_ber4_length(pb, pkt->size); // write length
2993
        avio_write(pb, pkt->data, pkt->size);
2994 2995
        mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size);
    }
2996

2997
    avio_flush(pb);
2998

2999 3000 3001
    return 0;
}

3002 3003 3004
static void mxf_write_random_index_pack(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
3005
    AVIOContext *pb = s->pb;
3006
    uint64_t pos = avio_tell(pb);
3007
    int i;
3008

3009
    avio_write(pb, random_index_pack_key, 16);
3010
    klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count);
3011

3012
    if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer)
3013
        avio_wb32(pb, 1); // BodySID of header partition
3014
    else
3015 3016
        avio_wb32(pb, 0);
    avio_wb64(pb, 0); // offset of header partition
3017

3018
    for (i = 0; i < mxf->body_partitions_count; i++) {
3019 3020
        avio_wb32(pb, 1); // BodySID
        avio_wb64(pb, mxf->body_partition_offset[i]);
3021 3022
    }

3023 3024
    avio_wb32(pb, 0); // BodySID of footer partition
    avio_wb64(pb, mxf->footer_partition_offset);
3025

3026
    avio_wb32(pb, avio_tell(pb) - pos + 4);
3027 3028
}

3029
static int mxf_write_footer(AVFormatContext *s)
3030
{
3031
    MXFContext *mxf = s->priv_data;
3032
    AVIOContext *pb = s->pb;
3033
    int i, err = 0;
3034

3035 3036 3037 3038 3039 3040 3041
    if (!mxf->header_written ||
        (s->oformat == &ff_mxf_opatom_muxer && !mxf->body_partition_offset)) {
        /* reason could be invalid options/not supported codec/out of memory */
        err = AVERROR_UNKNOWN;
        goto end;
    }

3042 3043
    mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;

3044
    mxf_write_klv_fill(s);
3045
    mxf->footer_partition_offset = avio_tell(pb);
3046
    if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { // no need to repeat index
3047
        if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0)
3048
            goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3049
    } else {
3050
        if ((err = mxf_write_partition(s, 0, 2, footer_partition_key, 0)) < 0)
3051
            goto end;
3052 3053
        mxf_write_klv_fill(s);
        mxf_write_index_table_segment(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3054
    }
3055

3056
    mxf_write_klv_fill(s);
3057 3058
    mxf_write_random_index_pack(s);

3059
    if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
3060
        if (s->oformat == &ff_mxf_opatom_muxer) {
3061 3062 3063
            /* rewrite body partition to update lengths */
            avio_seek(pb, mxf->body_partition_offset[0], SEEK_SET);
            if ((err = mxf_write_opatom_body_partition(s)) < 0)
3064
                goto end;
3065 3066
        }

3067
        avio_seek(pb, 0, SEEK_SET);
3068
        if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) {
3069
            if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0)
3070
                goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3071 3072
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
3073
        } else {
3074
            if ((err = mxf_write_partition(s, 0, 0, header_closed_partition_key, 1)) < 0)
3075
                goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3076
        }
3077 3078 3079 3080 3081
        // update footer partition offset
        for (i = 0; i < mxf->body_partitions_count; i++) {
            avio_seek(pb, mxf->body_partition_offset[i]+44, SEEK_SET);
            avio_wb64(pb, mxf->footer_partition_offset);
        }
3082
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3083

3084
end:
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3085 3086
    ff_audio_interleave_close(s);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
3087
    av_freep(&mxf->index_entries);
3088
    av_freep(&mxf->body_partition_offset);
3089 3090
    av_freep(&mxf->timecode_track->priv_data);
    av_freep(&mxf->timecode_track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3091

3092
    mxf_free(s);
3093

3094
    return err < 0 ? err : 0;
3095
}
3096

3097
static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
3098
{
3099 3100 3101 3102
    int i, stream_count = 0;

    for (i = 0; i < s->nb_streams; i++)
        stream_count += !!s->streams[i]->last_in_packet_buffer;
3103 3104

    if (stream_count && (s->nb_streams == stream_count || flush)) {
3105
        AVPacketList *pktl = s->internal->packet_buffer;
3106
        if (s->nb_streams != stream_count) {
3107
            AVPacketList *last = NULL;
3108
            // find last packet in edit unit
3109
            while (pktl) {
3110
                if (!stream_count || pktl->pkt.stream_index == 0)
3111
                    break;
3112 3113 3114
                // update last packet in packet buffer
                if (s->streams[pktl->pkt.stream_index]->last_in_packet_buffer != pktl)
                    s->streams[pktl->pkt.stream_index]->last_in_packet_buffer = pktl;
3115
                last = pktl;
3116
                pktl = pktl->next;
3117
                stream_count--;
3118
            }
3119 3120 3121
            // purge packet queue
            while (pktl) {
                AVPacketList *next = pktl->next;
3122
                av_packet_unref(&pktl->pkt);
3123 3124 3125
                av_freep(&pktl);
                pktl = next;
            }
3126 3127 3128
            if (last)
                last->next = NULL;
            else {
3129 3130
                s->internal->packet_buffer = NULL;
                s->internal->packet_buffer_end= NULL;
3131
                goto out;
3132
            }
3133
            pktl = s->internal->packet_buffer;
3134 3135
        }

3136
        *out = pktl->pkt;
3137
        av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts);
3138
        s->internal->packet_buffer = pktl->next;
3139 3140
        if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
            s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
3141 3142
        if(!s->internal->packet_buffer)
            s->internal->packet_buffer_end= NULL;
3143
        av_freep(&pktl);
3144 3145
        return 1;
    } else {
3146
    out:
3147 3148 3149 3150 3151 3152 3153
        av_init_packet(out);
        return 0;
    }
}

static int mxf_compare_timestamps(AVFormatContext *s, AVPacket *next, AVPacket *pkt)
{
3154 3155
    MXFStreamContext *sc  = s->streams[pkt ->stream_index]->priv_data;
    MXFStreamContext *sc2 = s->streams[next->stream_index]->priv_data;
3156

3157 3158
    return next->dts > pkt->dts ||
        (next->dts == pkt->dts && sc->order < sc2->order);
3159 3160 3161 3162
}

static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
{
3163
    return ff_audio_rechunk_interleave(s, out, pkt, flush,
3164
                               mxf_interleave_get_packet, mxf_compare_timestamps);
3165 3166
}

3167
#define MXF_COMMON_OPTIONS \
3168
    { "signal_standard", "Force/set Signal Standard",\
3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186
      offsetof(MXFContext, signal_standard), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "bt601", "ITU-R BT.601 and BT.656, also SMPTE 125M (525 and 625 line interlaced)",\
      0, AV_OPT_TYPE_CONST, {.i64 = 1}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "bt1358", "ITU-R BT.1358 and ITU-R BT.799-3, also SMPTE 293M (525 and 625 line progressive)",\
      0, AV_OPT_TYPE_CONST, {.i64 = 2}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "smpte347m", "SMPTE 347M (540 Mbps mappings)",\
      0, AV_OPT_TYPE_CONST, {.i64 = 3}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "smpte274m", "SMPTE 274M (1125 line)",\
      0, AV_OPT_TYPE_CONST, {.i64 = 4}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "smpte296m", "SMPTE 296M (750 line progressive)",\
      0, AV_OPT_TYPE_CONST, {.i64 = 5}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "smpte349m", "SMPTE 349M (1485 Mbps mappings)",\
      0, AV_OPT_TYPE_CONST, {.i64 = 6}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
    { "smpte428", "SMPTE 428-1 DCDM",\
      0, AV_OPT_TYPE_CONST, {.i64 = 7}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},



3187
static const AVOption mxf_options[] = {
3188
    MXF_COMMON_OPTIONS
3189 3190
    { "store_user_comments", "",
      offsetof(MXFContext, store_user_comments), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
3191 3192 3193 3194 3195 3196 3197 3198 3199 3200
    { NULL },
};

static const AVClass mxf_muxer_class = {
    .class_name     = "MXF muxer",
    .item_name      = av_default_item_name,
    .option         = mxf_options,
    .version        = LIBAVUTIL_VERSION_INT,
};

3201
static const AVOption d10_options[] = {
3202
    { "d10_channelcount", "Force/set channelcount in generic sound essence descriptor",
3203
      offsetof(MXFContext, channel_count), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 8, AV_OPT_FLAG_ENCODING_PARAM},
3204
    MXF_COMMON_OPTIONS
3205 3206
    { "store_user_comments", "",
      offsetof(MXFContext, store_user_comments), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
3207 3208 3209 3210 3211 3212 3213 3214 3215 3216
    { NULL },
};

static const AVClass mxf_d10_muxer_class = {
    .class_name     = "MXF-D10 muxer",
    .item_name      = av_default_item_name,
    .option         = d10_options,
    .version        = LIBAVUTIL_VERSION_INT,
};

3217 3218 3219
static const AVOption opatom_options[] = {
    { "mxf_audio_edit_rate", "Audio edit rate for timecode",
        offsetof(MXFContext, audio_edit_rate), AV_OPT_TYPE_RATIONAL, {.dbl=25}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
3220
    MXF_COMMON_OPTIONS
3221 3222
    { "store_user_comments", "",
      offsetof(MXFContext, store_user_comments), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
    { NULL },
};

static const AVClass mxf_opatom_muxer_class = {
    .class_name     = "MXF-OPAtom muxer",
    .item_name      = av_default_item_name,
    .option         = opatom_options,
    .version        = LIBAVUTIL_VERSION_INT,
};

3233
AVOutputFormat ff_mxf_muxer = {
3234
    .name              = "mxf",
3235
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
3236 3237 3238
    .mime_type         = "application/mxf",
    .extensions        = "mxf",
    .priv_data_size    = sizeof(MXFContext),
3239 3240
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
3241 3242 3243 3244 3245
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
3246
    .priv_class        = &mxf_muxer_class,
3247
};
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3248

3249
AVOutputFormat ff_mxf_d10_muxer = {
3250
    .name              = "mxf_d10",
3251
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"),
3252 3253
    .mime_type         = "application/mxf",
    .priv_data_size    = sizeof(MXFContext),
3254 3255
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
3256 3257 3258 3259 3260
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
3261
    .priv_class        = &mxf_d10_muxer_class,
Baptiste Coudurier's avatar
Baptiste Coudurier committed
3262
};
3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276

AVOutputFormat ff_mxf_opatom_muxer = {
    .name              = "mxf_opatom",
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) Operational Pattern Atom"),
    .mime_type         = "application/mxf",
    .extensions        = "mxf",
    .priv_data_size    = sizeof(MXFContext),
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_DNXHD,
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
3277
    .priv_class        = &mxf_opatom_muxer_class,
3278
};