mxfenc.c 107 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 25
 * signal_standard, color_siting, store_user_comments and klv_fill_key version
 * 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/h264.h"
52
#include "libavcodec/internal.h"
53
#include "audiointerleave.h"
54
#include "avformat.h"
Paul B Mahol's avatar
Paul B Mahol committed
55
#include "avio_internal.h"
56
#include "internal.h"
57
#include "mxf.h"
58
#include "config.h"
59

60
extern AVOutputFormat ff_mxf_d10_muxer;
61
extern AVOutputFormat ff_mxf_opatom_muxer;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
62

63
#define EDIT_UNITS_PER_BODY 250
64
#define KAG_SIZE 512
65

66
typedef struct MXFLocalTagPair {
67 68 69 70
    int local_tag;
    UID uid;
} MXFLocalTagPair;

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

78
typedef struct MXFStreamContext {
79
    AudioInterleaveContext aic;
80
    UID track_essence_element_key;
81
    int index;               ///< index in mxf_essence_container_uls table
82
    const UID *codec_ul;
83
    int order;               ///< interleaving order if dts are equal
84
    int interlaced;          ///< whether picture is interlaced
85
    int field_dominance;     ///< tff=1, bff=2
86
    int component_depth;
87
    int color_siting;
88
    int signal_standard;
89
    int h_chroma_sub_sample;
90
    int temporal_reordering;
91
    AVRational aspect_ratio; ///< display aspect ratio
92
    int closed_gop;          ///< gop is closed, used in mpeg-2 frame parsing
93
    int video_bit_rate;
94 95
} MXFStreamContext;

96
typedef struct MXFContainerEssenceEntry {
97 98
    UID container_ul;
    UID element_ul;
99
    UID codec_ul;
100
    void (*write_desc)(AVFormatContext *, AVStream *);
101
} MXFContainerEssenceEntry;
102

103
static const struct {
104
    enum AVCodecID id;
105 106
    int index;
} mxf_essence_mappings[] = {
107 108 109
    { AV_CODEC_ID_MPEG2VIDEO, 0 },
    { AV_CODEC_ID_PCM_S24LE,  1 },
    { AV_CODEC_ID_PCM_S16LE,  1 },
110 111
    { AV_CODEC_ID_DVVIDEO,   15 },
    { AV_CODEC_ID_DNXHD,     24 },
112
    { AV_CODEC_ID_JPEG2000,  34 },
113
    { AV_CODEC_ID_H264,      35 },
114
    { AV_CODEC_ID_NONE }
115 116
};

117
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st);
118
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st);
119
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
120 121
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
122

123
static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
124
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 },
125
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
126
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
127
      mxf_write_mpegvideo_desc },
128 129 130
    { { 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 },
131
      mxf_write_aes3_desc },
132
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 },
133
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x16,0x01,0x01,0x00 },
134
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
135
      mxf_write_wav_desc },
Baptiste Coudurier's avatar
Baptiste Coudurier committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    // 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 },
190
    // DV Unknown
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
    { { 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 },
    // 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 },
    // DV50 525/60
    { { 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 },
235 236 237
    // DNxHD 1080p 10bit high
    { { 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 },
238
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 },
239 240 241 242
      mxf_write_cdci_desc },
    // DNxHD 1080p 8bit medium
    { { 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 },
243
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 },
244 245 246 247
      mxf_write_cdci_desc },
    // DNxHD 1080p 8bit high
    { { 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 },
248
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 },
249 250 251 252
      mxf_write_cdci_desc },
    // DNxHD 1080i 10bit high
    { { 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 },
253
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 },
254 255 256 257
      mxf_write_cdci_desc },
    // DNxHD 1080i 8bit medium
    { { 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 },
258
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 },
259 260 261 262
      mxf_write_cdci_desc },
    // DNxHD 1080i 8bit high
    { { 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 },
263
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 },
264 265 266 267
      mxf_write_cdci_desc },
    // DNxHD 720p 10bit
    { { 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 },
268
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 },
269 270 271 272
      mxf_write_cdci_desc },
    // DNxHD 720p 8bit high
    { { 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 },
273
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 },
274 275 276 277
      mxf_write_cdci_desc },
    // DNxHD 720p 8bit medium
    { { 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 },
278
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 },
279 280 281 282
      mxf_write_cdci_desc },
    // DNxHD 720p 8bit low
    { { 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 },
283
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 },
284
      mxf_write_cdci_desc },
285 286 287 288 289
    // 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 },
290 291 292 293 294
    // 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 },
      mxf_write_mpegvideo_desc },
295
    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
296
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
297
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
298
      NULL },
299 300
};

301
typedef struct MXFContext {
302
    AVClass *av_class;
303
    int64_t footer_partition_offset;
304
    int essence_container_count;
305
    AVRational time_base;
306
    int header_written;
307 308
    MXFIndexEntry *index_entries;
    unsigned edit_units_count;
309
    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
310
    uint8_t slice_count;  ///< index slice count minus 1 (1 if no audio, 0 otherwise)
311 312 313 314
    int last_indexed_edit_unit;
    uint64_t *body_partition_offset;
    unsigned body_partitions_count;
    int last_key_index;  ///< index of last key frame
315
    uint64_t duration;
316
    AVTimecode tc;       ///< timecode context
317 318
    AVStream *timecode_track;
    int timecode_base;       ///< rounded time code base (25 or 30)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
319
    int edit_unit_byte_count; ///< fixed edit unit byte count
320
    uint64_t body_offset;
321 322
    uint32_t instance_number;
    uint8_t umid[16];        ///< unique material identifier
323
    int channel_count;
324
    int signal_standard;
325
    uint32_t tagged_value_count;
326
    AVRational audio_edit_rate;
327
    int store_user_comments;
328
} MXFContext;
329

330
static const uint8_t uuid_base[]            = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
331
static const uint8_t umid_ul[]              = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 };
332 333 334 335

/**
 * complete key for operation pattern, partitions, and primer pack
 */
336
static const uint8_t op1a_ul[]                     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x01,0x09,0x00 };
337
static const uint8_t opatom_ul[]                   = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x02,0x01,0x10,0x03,0x00,0x00 };
338 339 340 341
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 };
342 343
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
344
static const uint8_t klv_fill_key[]                = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 };
345
static const uint8_t body_partition_key[]          = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }; // ClosedComplete
346

347 348 349 350
/**
 * 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 };
351
static const uint8_t multiple_desc_ul[]     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x0D,0x01,0x03,0x01,0x02,0x7F,0x01,0x00 };
352

353 354
/**
 * SMPTE RP210 http://www.smpte-ra.org/mdd/index.html
355
 *             https://smpte-ra.org/sites/default/files/Labels.xml
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
 */
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 */
    { 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 */
371
    { 0x3C04, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x05,0x01,0x00,0x00}}, /* Version String */
372 373 374 375
    { 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 */
    // Content Storage
    { 0x1901, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x05,0x01,0x00,0x00}}, /* Package strong reference batch */
376
    { 0x1902, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x05,0x02,0x00,0x00}}, /* Package strong reference batch */
377 378 379 380 381 382 383
    // 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 */
384
    { 0x4402, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x03,0x03,0x02,0x01,0x00,0x00,0x00}}, /* Package Name */
385 386 387 388
    { 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 */
389
    { 0x4804, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x01,0x04,0x01,0x03,0x00,0x00,0x00,0x00}}, /* Track Number */
390 391 392 393 394 395 396 397
    { 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
398
    { 0x1201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x04,0x00,0x00}}, /* Start position */
399 400
    { 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 */
401 402 403 404
    // 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 */
405 406
    // File Descriptor
    { 0x3F01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x04,0x06,0x0B,0x00,0x00}}, /* Sub Descriptors reference array */
407 408
    { 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 */
409
    { 0x3002, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x02,0x00,0x00,0x00,0x00}}, /* ContainerDuration */
410 411
    { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* Essence Container */
    // Generic Picture Essence Descriptor
412
    { 0x320C, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Frame Layout */
413
    { 0x320D, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x02,0x05,0x00,0x00,0x00}}, /* Video Line Map */
414 415
    { 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 */
416 417
    { 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 */
418
    { 0x320B, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0E,0x00,0x00,0x00}}, /* Presentation Y offset */
419 420
    { 0x320E, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x00,0x00,0x00}}, /* Aspect Ratio */
    { 0x3201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}}, /* Picture Essence Coding */
421
    { 0x3212, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x01,0x06,0x00,0x00,0x00}}, /* Field Dominance (Opt) */
422
    { 0x3215, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x05,0x01,0x13,0x00,0x00,0x00,0x00}}, /* Signal Standard */
423 424 425
    // 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 */
426
    { 0x3303, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x06,0x00,0x00,0x00}}, /* Color Siting */
427
    // Generic Sound Essence Descriptor
428
    { 0x3D02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Locked/Unlocked */
429 430 431
    { 0x3D03, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x01,0x01,0x01,0x00,0x00}}, /* Audio sampling rate */
    { 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 */
432
    { 0x3D06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x02,0x04,0x02,0x00,0x00,0x00,0x00}}, /* Sound Essence Compression */
433 434 435 436
    // 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 */
437
    { 0x3F05, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x06,0x02,0x01,0x00,0x00,0x00,0x00}}, /* Edit Unit Byte Count */
438 439 440 441
    { 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
442 443
    // MPEG video Descriptor
    { 0x8000, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0B,0x00,0x00}}, /* BitRate */
444
    { 0x8007, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0A,0x00,0x00}}, /* ProfileAndLevel */
445 446 447
    // 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 */
448 449
};

450 451 452 453 454 455
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 */
};

456
static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value)
457
{
458 459 460
    avio_write(pb, uuid_base, 12);
    avio_wb16(pb, type);
    avio_wb16(pb, value);
461 462
}

463
static void mxf_write_umid(AVFormatContext *s, int type)
464
{
465
    MXFContext *mxf = s->priv_data;
466 467 468 469
    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);
470
}
471

472
static void mxf_write_refs_count(AVIOContext *pb, int ref_count)
473
{
474 475
    avio_wb32(pb, ref_count);
    avio_wb32(pb, 16);
476 477
}

478 479 480 481 482 483 484 485
static int klv_ber_length(uint64_t len)
{
    if (len < 128)
        return 1;
    else
        return (av_log2(len) >> 3) + 2;
}

486
static int klv_encode_ber_length(AVIOContext *pb, uint64_t len)
487 488 489 490 491
{
    // Determine the best BER size
    int size;
    if (len < 128) {
        //short form
492
        avio_w8(pb, len);
493 494 495 496 497 498
        return 1;
    }

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

    // long form
499
    avio_w8(pb, 0x80 + size);
500
    while(size) {
501
        size--;
502
        avio_w8(pb, len >> 8 * size & 0xff);
503 504 505 506
    }
    return 0;
}

507
static void klv_encode_ber4_length(AVIOContext *pb, int len)
508
{
509 510
    avio_w8(pb, 0x80 + 3);
    avio_wb24(pb, len);
511 512
}

513 514 515 516 517 518
static void klv_encode_ber9_length(AVIOContext *pb, uint64_t len)
{
    avio_w8(pb, 0x80 + 8);
    avio_wb64(pb, len);
}

519
/*
520
 * Get essence container ul index
521
 */
522
static int mxf_get_essence_container_ul_index(enum AVCodecID id)
523
{
524
    int i;
525 526 527
    for (i = 0; mxf_essence_mappings[i].id; i++)
        if (mxf_essence_mappings[i].id == id)
            return mxf_essence_mappings[i].index;
528
    return -1;
529 530
}

531
static void mxf_write_primer_pack(AVFormatContext *s)
532
{
533
    MXFContext *mxf = s->priv_data;
534
    AVIOContext *pb = s->pb;
535 536
    int local_tag_number, i = 0;

537
    local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch);
538
    local_tag_number += mxf->store_user_comments * FF_ARRAY_ELEMS(mxf_user_comments_local_tag);
539

540
    avio_write(pb, primer_pack_key, 16);
541 542
    klv_encode_ber_length(pb, local_tag_number * 18 + 8);

543 544
    avio_wb32(pb, local_tag_number); // local_tag num
    avio_wb32(pb, 18); // item size, always 18 according to the specs
545

546
    for (i = 0; i < FF_ARRAY_ELEMS(mxf_local_tag_batch); i++) {
547 548
        avio_wb16(pb, mxf_local_tag_batch[i].local_tag);
        avio_write(pb, mxf_local_tag_batch[i].uid, 16);
549
    }
550 551 552 553 554
    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);
        }
555 556
}

557
static void mxf_write_local_tag(AVIOContext *pb, int size, int tag)
558
{
559 560
    avio_wb16(pb, tag);
    avio_wb16(pb, size);
561 562
}

563
static void mxf_write_metadata_key(AVIOContext *pb, unsigned int value)
564
{
565 566
    avio_write(pb, header_metadata_key, 13);
    avio_wb24(pb, value);
567 568
}

569 570 571 572 573
static void mxf_free(AVFormatContext *s)
{
    int i;

    for (i = 0; i < s->nb_streams; i++) {
574
        AVStream *st = s->streams[i];
575 576 577 578
        av_freep(&st->priv_data);
    }
}

579
static const MXFCodecUL *mxf_get_data_definition_ul(int type)
580
{
581 582 583
    const MXFCodecUL *uls = ff_mxf_data_definition_uls;
    while (uls->uid[0]) {
        if (type == uls->id)
584
            break;
585
        uls++;
586 587 588 589
    }
    return uls;
}

590 591 592 593
//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)

594
static void mxf_write_essence_container_refs(AVFormatContext *s)
595
{
596
    MXFContext *c = s->priv_data;
597
    AVIOContext *pb = s->pb;
598
    int i;
599

600
    mxf_write_refs_count(pb, DESCRIPTOR_COUNT(c->essence_container_count));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
601 602
    av_log(s,AV_LOG_DEBUG, "essence container count:%d\n", c->essence_container_count);
    for (i = 0; i < c->essence_container_count; i++) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
603
        MXFStreamContext *sc = s->streams[i]->priv_data;
604
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
605
    }
606 607 608

    if (c->essence_container_count > 1)
        avio_write(pb, multiple_desc_ul, 16);
609 610
}

611 612 613
static void mxf_write_preface(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
614
    AVIOContext *pb = s->pb;
615 616 617

    mxf_write_metadata_key(pb, 0x012f00);
    PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
618
    klv_encode_ber_length(pb, 130 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
619 620 621 622 623 624

    // 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);

625
    // last modified date
626
    mxf_write_local_tag(pb, 8, 0x3B02);
627
    avio_wb64(pb, mxf->timestamp);
628 629 630

    // write version
    mxf_write_local_tag(pb, 2, 0x3B05);
631
    avio_wb16(pb, 258); // v1.2
632 633 634 635 636 637 638 639 640 641

    // 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);

642
    // operational pattern
643
    mxf_write_local_tag(pb, 16, 0x3B09);
644 645 646 647
    if (s->oformat == &ff_mxf_opatom_muxer)
        avio_write(pb, opatom_ul, 16);
    else
        avio_write(pb, op1a_ul, 16);
648 649

    // write essence_container_refs
650
    mxf_write_local_tag(pb, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A);
651
    mxf_write_essence_container_refs(s);
652 653 654

    // write dm_scheme_refs
    mxf_write_local_tag(pb, 8, 0x3B0B);
655
    avio_wb64(pb, 0);
656 657
}

658
/*
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
 * 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:
675
        av_log(NULL, AV_LOG_ERROR, "Invalid UTF8 sequence in mxf_utf16len\n\n");
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
    }
    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
702
 */
703
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
704
{
705 706 707 708 709 710 711
    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;
    }

712
    mxf_write_local_tag(pb, size*2, tag);
713
    avio_put_str16be(pb, value);
714 715
}

716 717
static void mxf_write_identification(AVFormatContext *s)
{
718
    MXFContext *mxf = s->priv_data;
719
    AVIOContext *pb = s->pb;
720
    const char *company = "FFmpeg";
721
    const char *product = s->oformat != &ff_mxf_opatom_muxer ? "OP1a Muxer" : "OPAtom Muxer";
722
    const char *version;
723
    int length;
724 725 726 727

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

728
    version = s->flags & AVFMT_FLAG_BITEXACT ?
729
        "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
730 731 732
    length = 72 + mxf_utf16_local_tag_length(company) +
                  mxf_utf16_local_tag_length(product) +
                  mxf_utf16_local_tag_length(version);
733 734 735 736 737 738
    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
739

740 741 742
    // write generation uid
    mxf_write_local_tag(pb, 16, 0x3C09);
    mxf_write_uuid(pb, Identification, 1);
743 744
    mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
    mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
745
    mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
746 747 748 749 750

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

751
    // modification date
752
    mxf_write_local_tag(pb, 8, 0x3C06);
753
    avio_wb64(pb, mxf->timestamp);
754 755 756 757
}

static void mxf_write_content_storage(AVFormatContext *s)
{
758
    AVIOContext *pb = s->pb;
759 760 761

    mxf_write_metadata_key(pb, 0x011800);
    PRINT_KEY(s, "content storage key", pb->buf_ptr - 16);
762
    klv_encode_ber_length(pb, 92);
763 764 765 766 767

    // 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);
768

769 770 771 772 773
    // write package reference
    mxf_write_local_tag(pb, 16 * 2 + 8, 0x1901);
    mxf_write_refs_count(pb, 2);
    mxf_write_uuid(pb, MaterialPackage, 0);
    mxf_write_uuid(pb, SourcePackage, 0);
774 775 776 777 778

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

781
static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
782
{
783
    MXFContext *mxf = s->priv_data;
784
    AVIOContext *pb = s->pb;
785
    MXFStreamContext *sc = st->priv_data;
786 787 788 789 790 791 792

    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);
793
    mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, st->index);
794
    PRINT_KEY(s, "track uid", pb->buf_ptr - 16);
795

796 797
    // write track id
    mxf_write_local_tag(pb, 4, 0x4801);
798
    avio_wb32(pb, st->index+2);
799

800
    // write track number
801
    mxf_write_local_tag(pb, 4, 0x4804);
802
    if (type == MaterialPackage)
803
        avio_wb32(pb, 0); // track number of material package is 0
804
    else
805
        avio_write(pb, sc->track_essence_element_key + 12, 4);
806 807

    mxf_write_local_tag(pb, 8, 0x4B01);
808 809 810 811 812 813 814 815

    if (st == mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer){
        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);
    }
816 817 818

    // write origin
    mxf_write_local_tag(pb, 8, 0x4B02);
819
    avio_wb64(pb, 0);
820 821 822

    // write sequence refs
    mxf_write_local_tag(pb, 16, 0x4803);
823
    mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index);
824 825
}

826 827 828
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)
829
{
830
    MXFContext *mxf = s->priv_data;
831
    AVIOContext *pb = s->pb;
832

833 834
    // find data define uls
    mxf_write_local_tag(pb, 16, 0x0201);
835
    if (st == mxf->timecode_track)
836
        avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
837
    else {
838
        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codecpar->codec_type);
839
        avio_write(pb, data_def_ul->uid, 16);
840
    }
841 842 843

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

845
    if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){
846 847 848 849
        avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count);
    } else {
        avio_wb64(pb, mxf->duration);
    }
850 851
}

852
static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
853
{
854
    MXFContext *mxf = s->priv_data;
855
    AVIOContext *pb = s->pb;
856
    enum MXFMetadataSetType component;
857 858 859 860 861 862

    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);
863
    mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index);
864 865

    PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
866
    mxf_write_common_fields(s, st);
867 868 869 870

    // write structural component
    mxf_write_local_tag(pb, 16 + 8, 0x1001);
    mxf_write_refs_count(pb, 1);
871 872 873
    if (st == mxf->timecode_track)
        component = TimecodeComponent;
    else
874 875 876
        component = SourceClip;
    if (type == SourcePackage)
        component += TypeBottom;
877 878 879
    mxf_write_uuid(pb, component, st->index);
}

880
static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
881 882
{
    MXFContext *mxf = s->priv_data;
883
    AVIOContext *pb = s->pb;
884 885 886 887 888 889

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

    // UID
    mxf_write_local_tag(pb, 16, 0x3C0A);
890 891
    mxf_write_uuid(pb, type == MaterialPackage ? TimecodeComponent :
                   TimecodeComponent + TypeBottom, st->index);
892 893 894 895 896

    mxf_write_common_fields(s, st);

    // Start Time Code
    mxf_write_local_tag(pb, 8, 0x1501);
897
    avio_wb64(pb, mxf->tc.start);
898 899 900

    // Rounded Time Code Base
    mxf_write_local_tag(pb, 2, 0x1502);
901
    avio_wb16(pb, mxf->timecode_base);
902 903 904

    // Drop Frame
    mxf_write_local_tag(pb, 1, 0x1503);
905
    avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
906 907
}

908
static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
909
{
910
    AVIOContext *pb = s->pb;
911 912 913 914 915 916 917 918
    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);
919
    mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index);
920 921

    PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
922
    mxf_write_common_fields(s, st);
923 924 925

    // write start_position
    mxf_write_local_tag(pb, 8, 0x1201);
926
    avio_wb64(pb, 0);
927

928
    // write source package uid, end of the reference
929 930
    mxf_write_local_tag(pb, 32, 0x1101);
    if (type == SourcePackage) {
931
        for (i = 0; i < 4; i++)
932
            avio_wb64(pb, 0);
933
    } else
934
        mxf_write_umid(s, 1);
935

936
    // write source track id
937 938
    mxf_write_local_tag(pb, 4, 0x1102);
    if (type == SourcePackage)
939
        avio_wb32(pb, 0);
940
    else
941
        avio_wb32(pb, st->index+2);
942 943
}

944 945
static void mxf_write_multi_descriptor(AVFormatContext *s)
{
946
    MXFContext *mxf = s->priv_data;
947
    AVIOContext *pb = s->pb;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
948
    const uint8_t *ul;
949 950 951 952
    int i;

    mxf_write_metadata_key(pb, 0x014400);
    PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16);
953
    klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams);
954 955 956 957 958 959 960

    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);
961 962
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
963 964 965

    // write essence container ul
    mxf_write_local_tag(pb, 16, 0x3004);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
966 967
    if (mxf->essence_container_count > 1)
        ul = multiple_desc_ul;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
968 969 970 971
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
        ul = mxf_essence_container_uls[sc->index].container_ul;
    }
972
    avio_write(pb, ul, 16);
973 974 975 976

    // write sub descriptor refs
    mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01);
    mxf_write_refs_count(pb, s->nb_streams);
977
    for (i = 0; i < s->nb_streams; i++)
978 979 980
        mxf_write_uuid(pb, SubDescriptor, i);
}

981
static void mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
982
{
983
    MXFContext *mxf = s->priv_data;
984
    MXFStreamContext *sc = st->priv_data;
985
    AVIOContext *pb = s->pb;
986

987
    avio_write(pb, key, 16);
988
    klv_encode_ber4_length(pb, size+20+8+12+20);
989 990 991 992 993

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

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

996
    mxf_write_local_tag(pb, 8, 0x3001);
997 998
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
999

1000
    mxf_write_local_tag(pb, 16, 0x3004);
1001
    avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
1002 1003
}

1004 1005
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 };
1006
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
1007 1008
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 };
1009

1010
static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1011
{
1012
    MXFStreamContext *sc = st->priv_data;
1013
    AVIOContext *pb = s->pb;
1014
    int stored_height = (st->codecpar->height+15)/16*16;
1015
    int display_height;
1016
    int f1, f2;
1017
    unsigned desc_size = size+8+8+8+8+8+8+8+5+16+4+12+20+5;
1018 1019
    if (sc->interlaced && sc->field_dominance)
        desc_size += 5;
1020 1021
    if (sc->signal_standard)
        desc_size += 5;
1022

1023
    mxf_write_generic_desc(s, st, key, desc_size);
1024 1025

    mxf_write_local_tag(pb, 4, 0x3203);
1026
    avio_wb32(pb, st->codecpar->width);
1027 1028

    mxf_write_local_tag(pb, 4, 0x3202);
1029
    avio_wb32(pb, stored_height>>sc->interlaced);
1030

1031
    mxf_write_local_tag(pb, 4, 0x3209);
1032
    avio_wb32(pb, st->codecpar->width);
1033

1034
    if (st->codecpar->height == 608) // PAL + VBI
1035
        display_height = 576;
1036
    else if (st->codecpar->height == 512)  // NTSC + VBI
1037 1038
        display_height = 486;
    else
1039
        display_height = st->codecpar->height;
1040

1041
    mxf_write_local_tag(pb, 4, 0x3208);
1042
    avio_wb32(pb, display_height>>sc->interlaced);
1043

1044 1045
    // presentation Y offset
    mxf_write_local_tag(pb, 4, 0x320B);
1046
    avio_wb32(pb, (st->codecpar->height - display_height)>>sc->interlaced);
1047

1048 1049
    // component depth
    mxf_write_local_tag(pb, 4, 0x3301);
1050
    avio_wb32(pb, sc->component_depth);
1051 1052 1053

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

1056 1057 1058 1059
    // color siting
    mxf_write_local_tag(pb, 1, 0x3303);
    avio_w8(pb, sc->color_siting);

1060 1061 1062 1063 1064
    if (sc->signal_standard) {
        mxf_write_local_tag(pb, 1, 0x3215);
        avio_w8(pb, sc->signal_standard);
    }

1065 1066
    // frame layout
    mxf_write_local_tag(pb, 1, 0x320C);
1067
    avio_w8(pb, sc->interlaced);
1068

1069
    // video line map
1070
    switch (st->codecpar->height) {
1071
    case  576: f1 = 23; f2 = st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
1072
    case  608: f1 =  7; f2 = 320; break;
1073
    case  480: f1 = 20; f2 = st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
    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;
    }

    if (!sc->interlaced) {
        f2  = 0;
        f1 *= 2;
    }

1085 1086 1087

    mxf_write_local_tag(pb, 16, 0x320D);
    avio_wb32(pb, 2);
1088 1089
    avio_wb32(pb, 4);
    avio_wb32(pb, f1);
1090
    avio_wb32(pb, f2);
1091

1092
    mxf_write_local_tag(pb, 8, 0x320E);
1093 1094
    avio_wb32(pb, sc->aspect_ratio.num);
    avio_wb32(pb, sc->aspect_ratio.den);
1095 1096

    mxf_write_local_tag(pb, 16, 0x3201);
1097
    avio_write(pb, *sc->codec_ul, 16);
1098 1099 1100 1101 1102 1103

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

1104 1105
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1106 1107
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
{
1108
    mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1109 1110
}

1111 1112
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
{
1113
    AVIOContext *pb = s->pb;
1114
    MXFStreamContext *sc = st->priv_data;
1115
    int profile_and_level = (st->codecpar->profile<<4) | st->codecpar->level;
1116

1117
    if (st->codecpar->codec_id != AV_CODEC_ID_H264) {
1118
        mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5);
1119

1120 1121 1122
        // bit rate
        mxf_write_local_tag(pb, 4, 0x8000);
        avio_wb32(pb, sc->video_bit_rate);
1123

1124 1125
        // profile and level
        mxf_write_local_tag(pb, 1, 0x8007);
1126
        if (!st->codecpar->profile)
1127 1128
            profile_and_level |= 0x80; // escape bit
        avio_w8(pb, profile_and_level);
1129 1130 1131
    } else {
        mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 0);
    }
1132 1133 1134
}

static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1135
{
1136
    AVIOContext *pb = s->pb;
1137 1138
    MXFContext *mxf = s->priv_data;
    int show_warnings = !mxf->footer_partition_offset;
1139 1140 1141 1142
    int duration_size = 0;

    if (s->oformat == &ff_mxf_opatom_muxer)
        duration_size = 12;
1143

1144 1145 1146 1147 1148 1149
    mxf_write_generic_desc(s, st, key, size+duration_size+5+12+8+8);

    if (duration_size > 0){
        mxf_write_local_tag(pb, 8, 0x3002);
        avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count);
    }
1150

1151
    // audio locked
1152
    mxf_write_local_tag(pb, 1, 0x3D02);
1153
    avio_w8(pb, 1);
1154 1155 1156

    // write audio sampling rate
    mxf_write_local_tag(pb, 8, 0x3D03);
1157
    avio_wb32(pb, st->codecpar->sample_rate);
1158
    avio_wb32(pb, 1);
1159 1160

    mxf_write_local_tag(pb, 4, 0x3D07);
1161
    if (mxf->channel_count == -1) {
1162
        if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codecpar->channels != 4) && (st->codecpar->channels != 8))
1163
            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");
1164
        avio_wb32(pb, st->codecpar->channels);
1165
    } else if (s->oformat == &ff_mxf_d10_muxer) {
1166
        if (show_warnings && (mxf->channel_count < st->codecpar->channels))
1167
            av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n");
1168
        if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8))
1169
            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");
1170 1171
        avio_wb32(pb, mxf->channel_count);
    } else {
1172
        avio_wb32(pb, st->codecpar->channels);
1173
    }
1174 1175

    mxf_write_local_tag(pb, 4, 0x3D01);
1176
    avio_wb32(pb, av_get_bits_per_sample(st->codecpar->codec_id));
1177 1178
}

1179
static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1180
{
1181
    AVIOContext *pb = s->pb;
1182

1183
    mxf_write_generic_sound_common(s, st, key, size+6+8);
1184 1185

    mxf_write_local_tag(pb, 2, 0x3D0A);
1186
    avio_wb16(pb, st->codecpar->block_align);
1187 1188 1189

    // avg bytes per sec
    mxf_write_local_tag(pb, 4, 0x3D09);
1190
    avio_wb32(pb, st->codecpar->block_align*st->codecpar->sample_rate);
1191 1192
}

1193
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st)
1194
{
1195
    mxf_write_wav_common(s, st, mxf_wav_descriptor_key, 0);
1196
}
1197

1198 1199
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st)
{
1200
    mxf_write_wav_common(s, st, mxf_aes3_descriptor_key, 0);
1201 1202
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1203 1204
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st)
{
1205
    mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1206 1207
}

1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
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;
}

1257
static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, const char *package_name)
1258
{
1259
    MXFContext *mxf = s->priv_data;
1260
    AVIOContext *pb = s->pb;
1261
    int i, track_count = s->nb_streams+1;
1262
    int name_size = mxf_utf16_local_tag_length(package_name);
1263
    int user_comment_count = 0;
1264 1265

    if (type == MaterialPackage) {
1266 1267
        if (mxf->store_user_comments)
            user_comment_count = mxf_write_user_comments(s, s->metadata);
1268 1269
        mxf_write_metadata_key(pb, 0x013600);
        PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
1270
        klv_encode_ber_length(pb, 92 + name_size + (16*track_count) + (16*user_comment_count) + 12LL*mxf->store_user_comments);
1271 1272 1273
    } else {
        mxf_write_metadata_key(pb, 0x013700);
        PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
1274
        klv_encode_ber_length(pb, 112 + name_size + (16*track_count) + 12LL*mxf->store_user_comments); // 20 bytes length for descriptor reference
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
    }

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

    // write package umid
    mxf_write_local_tag(pb, 32, 0x4401);
1285
    mxf_write_umid(s, type == SourcePackage);
1286 1287
    PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16);

1288 1289 1290 1291
    // package name
    if (name_size)
        mxf_write_local_tag_utf16(pb, 0x4402, package_name);

1292
    // package creation date
1293
    mxf_write_local_tag(pb, 8, 0x4405);
1294
    avio_wb64(pb, mxf->timestamp);
1295

1296
    // package modified date
1297
    mxf_write_local_tag(pb, 8, 0x4404);
1298
    avio_wb64(pb, mxf->timestamp);
1299 1300

    // write track refs
1301 1302
    mxf_write_local_tag(pb, track_count*16 + 8, 0x4403);
    mxf_write_refs_count(pb, track_count);
1303 1304
    mxf_write_uuid(pb, type == MaterialPackage ? Track :
                   Track + TypeBottom, -1); // timecode track
1305 1306 1307
    for (i = 0; i < s->nb_streams; i++)
        mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, i);

1308
    // write user comment refs
1309 1310 1311 1312 1313 1314
    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);
    }
1315

1316 1317 1318
    // write multiple descriptor reference
    if (type == SourcePackage) {
        mxf_write_local_tag(pb, 16, 0x4701);
1319 1320 1321 1322 1323
        if (s->nb_streams > 1) {
            mxf_write_uuid(pb, MultipleDescriptor, 0);
            mxf_write_multi_descriptor(s);
        } else
            mxf_write_uuid(pb, SubDescriptor, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1324
    }
1325

1326 1327 1328 1329 1330
    // write timecode track
    mxf_write_track(s, mxf->timecode_track, type);
    mxf_write_sequence(s, mxf->timecode_track, type);
    mxf_write_timecode_component(s, mxf->timecode_track, type);

1331
    for (i = 0; i < s->nb_streams; i++) {
1332 1333 1334 1335
        AVStream *st = s->streams[i];
        mxf_write_track(s, st, type);
        mxf_write_sequence(s, st, type);
        mxf_write_structural_component(s, st, type);
1336 1337

        if (type == SourcePackage) {
1338
            MXFStreamContext *sc = st->priv_data;
1339
            mxf_essence_container_uls[sc->index].write_desc(s, st);
1340 1341 1342 1343
        }
    }
}

1344 1345
static int mxf_write_essence_container_data(AVFormatContext *s)
{
1346
    AVIOContext *pb = s->pb;
1347 1348

    mxf_write_metadata_key(pb, 0x012300);
1349
    klv_encode_ber_length(pb, 72);
1350 1351 1352 1353 1354

    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
1355
    mxf_write_umid(s, 1);
1356 1357

    mxf_write_local_tag(pb, 4, 0x3F07); // BodySID
1358
    avio_wb32(pb, 1);
1359

1360
    mxf_write_local_tag(pb, 4, 0x3F06); // IndexSID
1361
    avio_wb32(pb, 2);
1362

1363 1364 1365
    return 0;
}

1366 1367
static int mxf_write_header_metadata_sets(AVFormatContext *s)
{
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
    const char *material_package_name = NULL;
    const char *file_package_name = NULL;
    AVDictionaryEntry *entry = NULL;
    AVStream *st = NULL;
    int i;

    if (entry = av_dict_get(s->metadata, "material_package_name", NULL, 0))
       material_package_name = entry->value;

    if (entry = av_dict_get(s->metadata, "file_package_name", NULL, 0)) {
        file_package_name = entry->value;
    } 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)) {
                file_package_name = entry->value;
                break;
            }
        }
    }

1390
    mxf_write_preface(s);
1391 1392
    mxf_write_identification(s);
    mxf_write_content_storage(s);
1393 1394
    mxf_write_package(s, MaterialPackage, material_package_name);
    mxf_write_package(s, SourcePackage, file_package_name);
1395
    mxf_write_essence_container_data(s);
1396 1397 1398
    return 0;
}

1399
static unsigned klv_fill_size(uint64_t size)
1400
{
1401
    unsigned pad = KAG_SIZE - (size & (KAG_SIZE-1));
1402
    if (pad < 20) // smallest fill item possible
1403 1404 1405 1406 1407
        return pad + KAG_SIZE;
    else
        return pad & (KAG_SIZE-1);
}

1408
static void mxf_write_index_table_segment(AVFormatContext *s)
1409 1410
{
    MXFContext *mxf = s->priv_data;
1411
    AVIOContext *pb = s->pb;
1412
    int i, j, temporal_reordering = 0;
1413
    int key_index = mxf->last_key_index;
1414 1415 1416

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1417
    if (!mxf->edit_units_count && !mxf->edit_unit_byte_count)
1418 1419
        return;

1420
    avio_write(pb, index_table_segment_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1421 1422

    if (mxf->edit_unit_byte_count) {
1423
        klv_encode_ber_length(pb, 80);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1424
    } else {
1425 1426
        klv_encode_ber_length(pb, 85 + 12+(s->nb_streams+1LL)*6 +
                              12+mxf->edit_units_count*(11+mxf->slice_count*4LL));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1427
    }
1428 1429 1430 1431 1432 1433 1434

    // 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);
1435 1436
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
1437 1438 1439

    // index start position
    mxf_write_local_tag(pb, 8, 0x3F0C);
1440
    avio_wb64(pb, mxf->last_indexed_edit_unit);
1441 1442 1443

    // index duration
    mxf_write_local_tag(pb, 8, 0x3F0D);
1444
    if (mxf->edit_unit_byte_count)
1445
        avio_wb64(pb, 0); // index table covers whole container
1446
    else
1447
        avio_wb64(pb, mxf->edit_units_count);
1448 1449 1450

    // edit unit byte count
    mxf_write_local_tag(pb, 4, 0x3F05);
1451
    avio_wb32(pb, mxf->edit_unit_byte_count);
1452 1453 1454

    // index sid
    mxf_write_local_tag(pb, 4, 0x3F06);
1455
    avio_wb32(pb, 2);
1456 1457 1458

    // body sid
    mxf_write_local_tag(pb, 4, 0x3F07);
1459
    avio_wb32(pb, 1);
1460

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1461
    if (!mxf->edit_unit_byte_count) {
1462 1463
        // real slice count - 1
        mxf_write_local_tag(pb, 1, 0x3F08);
1464
        avio_w8(pb, mxf->slice_count);
1465

1466 1467
        // delta entry array
        mxf_write_local_tag(pb, 8 + (s->nb_streams+1)*6, 0x3F09);
1468 1469
        avio_wb32(pb, s->nb_streams+1); // num of entries
        avio_wb32(pb, 6);               // size of one entry
1470
        // write system item delta entry
1471 1472 1473
        avio_w8(pb, 0);
        avio_w8(pb, 0); // slice entry
        avio_wb32(pb, 0); // element delta
1474 1475 1476
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            MXFStreamContext *sc = st->priv_data;
1477
            avio_w8(pb, sc->temporal_reordering);
1478 1479 1480
            if (sc->temporal_reordering)
                temporal_reordering = 1;
            if (i == 0) { // video track
1481 1482
                avio_w8(pb, 0); // slice number
                avio_wb32(pb, KAG_SIZE); // system item size including klv fill
1483 1484 1485
            } else { // audio track
                unsigned audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
                audio_frame_size += klv_fill_size(audio_frame_size);
1486 1487
                avio_w8(pb, 1);
                avio_wb32(pb, (i-1)*audio_frame_size); // element delta
1488
            }
1489
        }
1490

1491
        mxf_write_local_tag(pb, 8 + mxf->edit_units_count*(11+mxf->slice_count*4), 0x3F0A);
1492 1493
        avio_wb32(pb, mxf->edit_units_count);  // num of entries
        avio_wb32(pb, 11+mxf->slice_count*4);  // size of one entry
1494

1495
        for (i = 0; i < mxf->edit_units_count; i++) {
1496
            int temporal_offset = 0;
1497

1498
            if (!(mxf->index_entries[i].flags & 0x33)) { // I-frame
1499 1500 1501 1502
                mxf->last_key_index = key_index;
                key_index = i;
            }

1503
            if (temporal_reordering) {
1504 1505 1506 1507 1508
                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;
1509
                    }
1510 1511 1512
                    if (j == mxf->edit_units_count)
                        av_log(s, AV_LOG_WARNING, "missing frames\n");
                    temporal_offset = j - key_index - pic_num_in_gop;
1513
                }
1514
            }
1515
            avio_w8(pb, temporal_offset);
1516 1517

            if ((mxf->index_entries[i].flags & 0x30) == 0x30) { // back and forward prediction
1518
                avio_w8(pb, mxf->last_key_index - i);
1519
            } else {
1520
                avio_w8(pb, key_index - i); // key frame offset
1521 1522 1523
                if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward
                    mxf->last_key_index = key_index;
            }
1524

1525
            if (!(mxf->index_entries[i].flags & 0x33) && // I-frame
1526 1527
                mxf->index_entries[i].flags & 0x40 && !temporal_offset)
                mxf->index_entries[i].flags |= 0x80; // random access
1528
            avio_w8(pb, mxf->index_entries[i].flags);
1529
            // stream offset
1530
            avio_wb64(pb, mxf->index_entries[i].offset);
1531
            if (s->nb_streams > 1)
1532
                avio_wb32(pb, mxf->index_entries[i].slice_offset);
1533
        }
1534

1535 1536 1537
        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
1538
    }
1539 1540
}

1541 1542
static void mxf_write_klv_fill(AVFormatContext *s)
{
1543
    unsigned pad = klv_fill_size(avio_tell(s->pb));
1544
    if (pad) {
1545
        avio_write(s->pb, klv_fill_key, 16);
1546 1547
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
1548
        ffio_fill(s->pb, 0, pad);
1549
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
1550 1551 1552
    }
}

1553
static int mxf_write_partition(AVFormatContext *s, int bodysid,
1554
                                int indexsid,
1555
                                const uint8_t *key, int write_metadata)
1556 1557
{
    MXFContext *mxf = s->priv_data;
1558
    AVIOContext *pb = s->pb;
1559
    int64_t header_byte_count_offset;
1560
    unsigned index_byte_count = 0;
1561
    uint64_t partition_offset = avio_tell(pb);
1562
    int err;
1563

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1564 1565 1566 1567
    if (!mxf->edit_unit_byte_count && mxf->edit_units_count)
        index_byte_count = 85 + 12+(s->nb_streams+1)*6 +
            12+mxf->edit_units_count*(11+mxf->slice_count*4);
    else if (mxf->edit_unit_byte_count && indexsid)
1568
        index_byte_count = 80;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1569 1570

    if (index_byte_count) {
1571 1572 1573
        // add encoded ber length
        index_byte_count += 16 + klv_ber_length(index_byte_count);
        index_byte_count += klv_fill_size(index_byte_count);
1574 1575
    }

1576
    if (key && !memcmp(key, body_partition_key, 16)) {
1577 1578 1579 1580 1581
        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;
        }
1582
        mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset;
1583
    }
1584

1585
    // write klv
1586 1587 1588 1589 1590
    if (key)
        avio_write(pb, key, 16);
    else
        avio_write(pb, body_partition_key, 16);

1591
    klv_encode_ber_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
1592 1593

    // write partition value
1594 1595 1596
    avio_wb16(pb, 1); // majorVersion
    avio_wb16(pb, 2); // minorVersion
    avio_wb32(pb, KAG_SIZE); // KAGSize
1597

1598
    avio_wb64(pb, partition_offset); // ThisPartition
1599

1600
    if (key && !memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
1601
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition
1602
    else if (key && !memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
1603
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
1604
    else
1605
        avio_wb64(pb, 0);
1606

1607
    avio_wb64(pb, mxf->footer_partition_offset); // footerPartition
1608 1609

    // set offset
1610
    header_byte_count_offset = avio_tell(pb);
1611
    avio_wb64(pb, 0); // headerByteCount, update later
1612

1613
    // indexTable
1614 1615
    avio_wb64(pb, index_byte_count); // indexByteCount
    avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
1616 1617

    // BodyOffset
1618
    if (bodysid && mxf->edit_units_count && mxf->body_partitions_count && s->oformat != &ff_mxf_opatom_muxer)
1619
        avio_wb64(pb, mxf->body_offset);
1620
    else
1621
        avio_wb64(pb, 0);
1622

1623
    avio_wb32(pb, bodysid); // bodySID
1624 1625

    // operational pattern
1626 1627 1628 1629
    if (s->oformat == &ff_mxf_opatom_muxer)
        avio_write(pb, opatom_ul, 16);
    else
        avio_write(pb, op1a_ul, 16);
1630 1631

    // essence container
1632
    mxf_write_essence_container_refs(s);
1633 1634 1635

    if (write_metadata) {
        // mark the start of the headermetadata and calculate metadata size
1636
        int64_t pos, start;
1637 1638
        unsigned header_byte_count;

1639
        mxf_write_klv_fill(s);
1640
        start = avio_tell(s->pb);
1641 1642
        mxf_write_primer_pack(s);
        mxf_write_header_metadata_sets(s);
1643
        pos = avio_tell(s->pb);
1644
        header_byte_count = pos - start + klv_fill_size(pos);
1645

1646
        // update header_byte_count
1647
        avio_seek(pb, header_byte_count_offset, SEEK_SET);
1648
        avio_wb64(pb, header_byte_count);
1649
        avio_seek(pb, pos, SEEK_SET);
1650 1651
    }

1652 1653
    if(key)
        avio_flush(pb);
1654 1655

    return 0;
1656 1657
}

1658 1659 1660 1661 1662 1663 1664
static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st,
AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
    MXFStreamContext *sc = st->priv_data;
    int i, cid;
    uint8_t* header_cid;
1665
    int frame_size = 0;
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675

    if (mxf->header_written)
        return 1;

    if (pkt->size < 43)
        return -1;

    header_cid = pkt->data + 0x28;
    cid = header_cid[0] << 24 | header_cid[1] << 16 | header_cid[2] << 8 | header_cid[3];

1676
    if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) < 0)
1677
        return -1;
1678 1679
    if ((sc->interlaced = avpriv_dnxhd_get_interlaced(cid)) < 0)
        return AVERROR_INVALIDDATA;
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718

    switch (cid) {
    case 1235:
        sc->index = 24;
        sc->component_depth = 10;
        break;
    case 1237:
        sc->index = 25;
        break;
    case 1238:
        sc->index = 26;
        break;
    case 1241:
        sc->index = 27;
        sc->component_depth = 10;
        break;
    case 1242:
        sc->index = 28;
        break;
    case 1243:
        sc->index = 29;
        break;
    case 1250:
        sc->index = 30;
        sc->component_depth = 10;
        break;
    case 1251:
        sc->index = 31;
        break;
    case 1252:
        sc->index = 32;
        break;
    case 1253:
        sc->index = 33;
        break;
    default:
        return -1;
    }

1719 1720
    sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
    sc->aspect_ratio = (AVRational){ 16, 9 };
1721

1722 1723 1724 1725 1726
    if(s->oformat == &ff_mxf_opatom_muxer){
        mxf->edit_unit_byte_count = frame_size;
        return 1;
    }

1727 1728 1729 1730
    mxf->edit_unit_byte_count = KAG_SIZE;
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MXFStreamContext *sc = st->priv_data;
1731
        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
1732 1733
            mxf->edit_unit_byte_count += 16 + 4 + sc->aic.samples[0]*sc->aic.sample_size;
            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
1734
        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1735 1736 1737 1738 1739 1740 1741 1742
            mxf->edit_unit_byte_count += 16 + 4 + frame_size;
            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
        }
    }

    return 1;
}

1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776
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;
    int i, ul_index, frame_size, stype, pal;

    if (mxf->header_written)
        return 1;

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

    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;

    if ((vs_pack[2] & 0x07) == 0x02)
        sc->aspect_ratio = (AVRational){ 16, 9 };
    else
        sc->aspect_ratio = (AVRational){ 4, 3 };

    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
        ul_index = 6 + pal;
        frame_size = pal ? 288000 : 240000;
        if (sc->interlaced) {
1777
            av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n");
1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796
            sc->interlaced = 0;
        }
        break;
    case 0x14: // DV100 1080i
        ul_index = 4 + pal;
        frame_size = pal ? 576000 : 480000;
        break;
    case 0x04: // DV50
        ul_index = 2 + pal;
        frame_size = pal ? 288000 : 240000;
        break;
    default: // DV25
        ul_index = 0 + pal;
        frame_size = pal ? 144000 : 120000;
    }

    sc->index = ul_index + 16;
    sc->codec_ul =  &mxf_essence_container_uls[sc->index].codec_ul;

1797 1798 1799 1800 1801
    if(s->oformat == &ff_mxf_opatom_muxer) {
        mxf->edit_unit_byte_count = frame_size;
        return 1;
    }

1802 1803 1804 1805
    mxf->edit_unit_byte_count = KAG_SIZE;
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MXFStreamContext *sc = st->priv_data;
1806
        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
1807 1808
            mxf->edit_unit_byte_count += 16 + 4 + sc->aic.samples[0]*sc->aic.sample_size;
            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
1809
        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1810 1811 1812 1813 1814 1815 1816 1817
            mxf->edit_unit_byte_count += 16 + 4 + frame_size;
            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
        }
    }

    return 1;
}

1818 1819 1820 1821 1822 1823
static const struct {
    UID uid;
    int frame_size;
    int profile;
    uint8_t interlaced;
} mxf_h264_codec_uls[] = {
1824
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 },      0,  66, 0 }, // AVC Baseline, Unconstrained Coding
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 },      0, 110, 0 }, // AVC High 10 Intra
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960,   0, 1 }, // AVC Intra 50 1080i60
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088,   0, 1 }, // AVC Intra 50 1080i50
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960,   0, 0 }, // AVC Intra 50 1080p30
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 281088,   0, 0 }, // AVC Intra 50 1080p25
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736,   0, 0 }, // AVC Intra 50 720p60
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, 140800,   0, 0 }, // AVC Intra 50 720p50
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 },      0, 122, 0 }, // AVC High 422 Intra
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576,   0, 1 }, // AVC Intra 100 1080i60
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832,   0, 1 }, // AVC Intra 100 1080i50
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576,   0, 0 }, // AVC Intra 100 1080p30
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, 568832,   0, 0 }, // AVC Intra 100 1080p25
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544,   0, 0 }, // AVC Intra 100 720p60
    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, 284672,   0, 0 }, // AVC Intra 100 720p50
};

static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
                                AVPacket *pkt, MXFIndexEntry *e)
{
    MXFContext *mxf = s->priv_data;
    MXFStreamContext *sc = st->priv_data;
    static const int mxf_h264_num_codec_uls = sizeof(mxf_h264_codec_uls) / sizeof(mxf_h264_codec_uls[0]);
    const uint8_t *buf = pkt->data;
    const uint8_t *buf_end = pkt->data + pkt->size;
    uint32_t state = -1;
    int extra_size = 512; // support AVC Intra files without SPS/PPS header
    int i, frame_size;
    uint8_t uid_found;

    if (pkt->size > extra_size)
        buf_end -= pkt->size - extra_size; // no need to parse beyond SPS/PPS header

    for (;;) {
        buf = avpriv_find_start_code(buf, buf_end, &state);
        if (buf >= buf_end)
            break;
        --buf;
        switch (state & 0x1f) {
James Almer's avatar
James Almer committed
1863
        case H264_NAL_SPS:
1864
            st->codecpar->profile = buf[1];
1865 1866
            e->flags |= 0x40;
            break;
James Almer's avatar
James Almer committed
1867
        case H264_NAL_PPS:
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
            if (e->flags & 0x40) { // sequence header present
                e->flags |= 0x80; // random access
                extra_size = 0;
                buf = buf_end;
            }
            break;
        default:
            break;
        }
    }

    if (mxf->header_written)
        return 1;

    sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
    sc->component_depth = 10; // AVC Intra is always 10 Bit
1884
    sc->interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
1885 1886 1887 1888 1889 1890 1891 1892 1893
    if (sc->interlaced)
        sc->field_dominance = 1; // top field first is mandatory for AVC Intra

    uid_found = 0;
    frame_size = pkt->size + extra_size;
    for (i = 0; i < mxf_h264_num_codec_uls; i++) {
        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;
            return 1;
1894
        } else if (st->codecpar->profile == mxf_h264_codec_uls[i].profile) {
1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907
            sc->codec_ul = &mxf_h264_codec_uls[i].uid;
            uid_found = 1;
        }
    }

    if (!uid_found) {
        av_log(s, AV_LOG_ERROR, "AVC Intra 50/100 supported only\n");
        return 0;
    }

    return 1;
}

1908 1909 1910 1911 1912 1913 1914 1915 1916
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
1917 1918
    { 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
1919 1920
};

1921
static const UID *mxf_get_mpeg2_codec_ul(AVCodecParameters *par)
1922
{
1923
    int long_gop = 1;
1924

1925 1926
    if (par->profile == 4) { // Main
        if (par->level == 8) // Main
1927
            return &mxf_mpeg2_codec_uls[0+long_gop];
1928
        else if (par->level == 4) // High
1929
            return &mxf_mpeg2_codec_uls[4+long_gop];
1930
        else if (par->level == 6) // High 14
1931
            return &mxf_mpeg2_codec_uls[8+long_gop];
1932 1933
    } else if (par->profile == 0) { // 422
        if (par->level == 5) // Main
1934
            return &mxf_mpeg2_codec_uls[2+long_gop];
1935
        else if (par->level == 2) // High
1936
            return &mxf_mpeg2_codec_uls[6+long_gop];
1937 1938 1939 1940
    }
    return NULL;
}

1941 1942
static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
                                 AVPacket *pkt, MXFIndexEntry *e)
1943 1944 1945 1946 1947 1948 1949
{
    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];
1950
        if (c == 0x1b5) {
1951
            if ((pkt->data[i+1] & 0xf0) == 0x10) { // seq ext
1952 1953
                st->codecpar->profile = pkt->data[i+1] & 0x07;
                st->codecpar->level   = pkt->data[i+2] >> 4;
1954 1955
            } else if (i + 5 < pkt->size && (pkt->data[i+1] & 0xf0) == 0x80) { // pict coding ext
                sc->interlaced = !(pkt->data[i+5] & 0x80); // progressive frame
1956 1957
                if (sc->interlaced)
                    sc->field_dominance = 1 + !(pkt->data[i+4] & 0x80); // top field first
1958 1959
                break;
            }
1960
        } else if (c == 0x1b8) { // gop
1961 1962
            if (pkt->data[i+4]>>6 & 0x01) { // closed
                sc->closed_gop = 1;
1963 1964
                if (e->flags & 0x40) // sequence header present
                    e->flags |= 0x80; // random access
1965
            }
1966
        } else if (c == 0x1b3) { // seq
1967
            e->flags |= 0x40;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1968 1969 1970 1971 1972 1973
            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,
1974
                          st->codecpar->width, st->codecpar->height, 1024*1024);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1975
            }
1976 1977
        } else if (c == 0x100) { // pic
            int pict_type = (pkt->data[i+2]>>3) & 0x07;
1978
            e->temporal_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
1979
            if (pict_type == 2) { // P-frame
1980
                e->flags |= 0x22;
1981 1982
                sc->closed_gop = 0; // reset closed GOP, don't matter anymore
            } else if (pict_type == 3) { // B-frame
1983
                if (sc->closed_gop)
1984
                    e->flags |= 0x13; // only backward prediction
1985
                else
1986
                    e->flags |= 0x33;
1987 1988 1989 1990 1991
                sc->temporal_reordering = -1;
            } else if (!pict_type) {
                av_log(s, AV_LOG_ERROR, "error parsing mpeg2 frame\n");
                return 0;
            }
1992 1993
        }
    }
1994
    if (s->oformat != &ff_mxf_d10_muxer)
1995
        sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar);
1996 1997 1998
    return !!sc->codec_ul;
}

1999 2000
static uint64_t mxf_parse_timestamp(time_t timestamp)
{
2001 2002
    struct tm tmbuf;
    struct tm *time = gmtime_r(&timestamp, &tmbuf);
2003 2004
    if (!time)
        return 0;
2005 2006 2007 2008 2009 2010 2011 2012
    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 |
                      time->tm_sec        << 8;
}

2013 2014 2015
static void mxf_gen_umid(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2016
    uint32_t seed = av_get_random_seed();
2017 2018 2019 2020 2021
    uint64_t umid = seed + 0x5294713400000000LL;

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

2022
    mxf->instance_number = seed & 0xFFFFFF;
2023 2024
}

2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037
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);
}

2038
static int mxf_write_header(AVFormatContext *s)
2039 2040
{
    MXFContext *mxf = s->priv_data;
2041
    int i, ret;
2042
    uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
2043
    const MXFSamplesPerFrame *spf = NULL;
2044
    int64_t timestamp = 0;
2045

2046 2047 2048
    if (!s->nb_streams)
        return -1;

2049 2050 2051 2052 2053
    if (s->oformat == &ff_mxf_opatom_muxer && s->nb_streams !=1){
        av_log(s, AV_LOG_ERROR, "there must be exactly one stream for mxf opatom\n");
        return -1;
    }

2054 2055 2056
    if (!av_dict_get(s->metadata, "comment_", NULL, AV_DICT_IGNORE_SUFFIX))
        mxf->store_user_comments = 0;

2057 2058
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
2059
        MXFStreamContext *sc = av_mallocz(sizeof(*sc));
2060 2061 2062
        if (!sc)
            return AVERROR(ENOMEM);
        st->priv_data = sc;
2063

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

2069
        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
2070
            const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(st->codecpar->format);
2071
            // TODO: should be avg_frame_rate
2072
            AVRational rate, tbc = st->time_base;
2073 2074
            // Default component depth to 8
            sc->component_depth = 8;
2075
            sc->h_chroma_sub_sample = 2;
2076
            sc->color_siting = 0xFF;
2077 2078

            if (pix_desc) {
2079
                sc->component_depth     = pix_desc->comp[0].depth;
2080
                sc->h_chroma_sub_sample = 1 << pix_desc->log2_chroma_w;
2081
            }
2082 2083 2084 2085 2086 2087
            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;
            }
2088

2089
            mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num;
2090
            spf = ff_mxf_get_samples_per_frame(s, tbc);
2091
            if (!spf) {
2092 2093 2094
                av_log(s, AV_LOG_ERROR, "Unsupported video frame rate %d/%d\n",
                       tbc.den, tbc.num);
                return AVERROR(EINVAL);
2095
            }
2096
            mxf->time_base = spf->time_base;
2097
            rate = av_inv_q(mxf->time_base);
2098
            avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
2099
            if((ret = mxf_init_timecode(s, st, rate)) < 0)
2100
                return ret;
2101

2102
            sc->video_bit_rate = st->codecpar->bit_rate;
2103
            if (s->oformat == &ff_mxf_d10_muxer) {
2104 2105 2106 2107
                if ((sc->video_bit_rate == 50000000) && (mxf->time_base.den == 25)) {
                    sc->index = 3;
                } else if ((sc->video_bit_rate == 49999840 || sc->video_bit_rate == 50000000) && (mxf->time_base.den != 25)) {
                    sc->index = 5;
2108
                } else if (sc->video_bit_rate == 40000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2109 2110
                    if (mxf->time_base.den == 25) sc->index = 7;
                    else                          sc->index = 9;
2111
                } else if (sc->video_bit_rate == 30000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2112 2113
                    if (mxf->time_base.den == 25) sc->index = 11;
                    else                          sc->index = 13;
2114
                } else {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2115 2116 2117 2118 2119
                    av_log(s, AV_LOG_ERROR, "error MXF D-10 only support 30/40/50 mbit/s\n");
                    return -1;
                }

                mxf->edit_unit_byte_count = KAG_SIZE; // system element
2120
                mxf->edit_unit_byte_count += 16 + 4 + (uint64_t)sc->video_bit_rate *
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2121 2122
                    mxf->time_base.num / (8*mxf->time_base.den);
                mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
2123
                mxf->edit_unit_byte_count += 16 + 4 + 4 + spf->samples_per_frame[0]*8*4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2124
                mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
2125 2126

                sc->signal_standard = 1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2127
            }
2128 2129
            if (mxf->signal_standard >= 0)
                sc->signal_standard = mxf->signal_standard;
2130 2131
        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            if (st->codecpar->sample_rate != 48000) {
2132 2133 2134
                av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
                return -1;
            }
2135
            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
2136
            if (s->oformat == &ff_mxf_d10_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2137 2138 2139 2140
                if (st->index != 1) {
                    av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n");
                    return -1;
                }
2141 2142
                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
2143 2144 2145
                    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;
2146 2147 2148
            } else if (s->oformat == &ff_mxf_opatom_muxer) {
                AVRational tbc = av_inv_q(mxf->audio_edit_rate);

2149 2150
                if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE &&
                    st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) {
2151 2152 2153
                    av_log(s, AV_LOG_ERROR, "Only pcm_s16le and pcm_s24le audio codecs are implemented\n");
                    return AVERROR_PATCHWELCOME;
                }
2154
                if (st->codecpar->channels != 1) {
2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
                    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);
                if (!spf){
                    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;
2170
                mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3;
2171 2172 2173 2174
                sc->index = 2;
            } else {
                mxf->slice_count = 1;
            }
2175
        }
2176

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2177
        if (!sc->index) {
2178
            sc->index = mxf_get_essence_container_ul_index(st->codecpar->codec_id);
2179 2180 2181 2182 2183
            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
2184
        }
2185

2186
        sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
2187

2188 2189
        memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15);
        sc->track_essence_element_key[15] = present[sc->index];
2190
        PRINT_KEY(s, "track essence element key", sc->track_essence_element_key);
2191 2192 2193 2194

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

2197
    if (s->oformat == &ff_mxf_d10_muxer || s->oformat == &ff_mxf_opatom_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2198 2199 2200
        mxf->essence_container_count = 1;
    }

2201
    if (!(s->flags & AVFMT_FLAG_BITEXACT))
2202 2203
        mxf_gen_umid(s);

2204 2205 2206 2207
    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];
2208 2209 2210 2211
        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);
2212 2213
    }

2214
    if (ff_parse_creation_time_metadata(s, &timestamp, 1) > 0)
2215
        mxf->timestamp = mxf_parse_timestamp(timestamp);
2216 2217 2218 2219 2220 2221 2222 2223
    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);
2224
    mxf->timecode_track->index = -1;
2225

2226
    if (!spf)
2227
        spf = ff_mxf_get_samples_per_frame(s, (AVRational){ 1, 25 });
2228

2229
    if (ff_audio_interleave_init(s, spf->samples_per_frame, mxf->time_base) < 0)
2230 2231
        return -1;

2232 2233 2234
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2235 2236 2237 2238 2239 2240
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;
2241
    AVIOContext *pb = s->pb;
2242
    unsigned frame;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2243 2244
    uint32_t time_code;

2245
    frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2246 2247

    // write system metadata pack
2248
    avio_write(pb, system_metadata_pack_key, 16);
2249
    klv_encode_ber4_length(pb, 57);
2250 2251 2252 2253
    avio_w8(pb, 0x5c); // UL, user date/time stamp, picture and sound item present
    avio_w8(pb, 0x04); // content package rate
    avio_w8(pb, 0x00); // content package type
    avio_wb16(pb, 0x00); // channel handle
2254
    avio_wb16(pb, (mxf->tc.start + frame) & 0xFFFF); // continuity count, supposed to overflow
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2255
    if (mxf->essence_container_count > 1)
2256
        avio_write(pb, multiple_desc_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2257 2258
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
2259
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2260
    }
2261 2262 2263
    avio_w8(pb, 0);
    avio_wb64(pb, 0);
    avio_wb64(pb, 0); // creation date/time stamp
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2264

2265
    avio_w8(pb, 0x81); // SMPTE 12M time code
2266
    time_code = av_timecode_get_smpte_from_framenum(&mxf->tc, frame);
2267 2268 2269
    avio_wb32(pb, time_code);
    avio_wb32(pb, 0); // binary group data
    avio_wb64(pb, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2270 2271

    // write system metadata package set
2272
    avio_write(pb, system_metadata_package_set_key, 16);
2273
    klv_encode_ber4_length(pb, 35);
2274 2275
    avio_w8(pb, 0x83); // UMID
    avio_wb16(pb, 0x20);
2276
    mxf_write_umid(s, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2277 2278
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2279 2280 2281
static void mxf_write_d10_video_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
2282
    AVIOContext *pb = s->pb;
2283 2284
    MXFStreamContext *sc = st->priv_data;
    int packet_size = (uint64_t)sc->video_bit_rate*mxf->time_base.num /
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2285 2286 2287 2288 2289 2290 2291
        (8*mxf->time_base.den); // frame size
    int pad;

    packet_size += 16 + 4;
    packet_size += klv_fill_size(packet_size);

    klv_encode_ber4_length(pb, pkt->size);
2292
    avio_write(pb, pkt->data, pkt->size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2293 2294 2295 2296

    // ensure CBR muxing by padding to correct video frame size
    pad = packet_size - pkt->size - 16 - 4;
    if (pad > 20) {
2297
        avio_write(s->pb, klv_fill_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2298 2299
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
2300
        ffio_fill(s->pb, 0, pad);
2301
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2302 2303
    } else {
        av_log(s, AV_LOG_WARNING, "cannot fill d-10 video packet\n");
Paul B Mahol's avatar
Paul B Mahol committed
2304
        ffio_fill(s->pb, 0, pad);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2305 2306 2307 2308 2309 2310
    }
}

static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
2311
    AVIOContext *pb = s->pb;
2312
    int frame_size = pkt->size / st->codecpar->block_align;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2313 2314 2315 2316 2317 2318
    uint8_t *samples = pkt->data;
    uint8_t *end = pkt->data + pkt->size;
    int i;

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

2319 2320
    avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1));
    avio_wl16(pb, frame_size);
2321
    avio_w8(pb, (1<<st->codecpar->channels)-1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2322 2323

    while (samples < end) {
2324
        for (i = 0; i < st->codecpar->channels; i++) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2325
            uint32_t sample;
2326
            if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
2327
                sample = AV_RL24(samples)<< 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2328 2329
                samples += 3;
            } else {
2330
                sample = AV_RL16(samples)<<12;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2331 2332
                samples += 2;
            }
2333
            avio_wl32(pb, sample | i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2334 2335
        }
        for (; i < 8; i++)
2336
            avio_wl32(pb, i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2337 2338 2339
    }
}

2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390
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;
}

2391
static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
2392
{
2393
    MXFContext *mxf = s->priv_data;
2394
    AVIOContext *pb = s->pb;
2395 2396
    AVStream *st = s->streams[pkt->stream_index];
    MXFStreamContext *sc = st->priv_data;
2397
    MXFIndexEntry ie = {0};
2398
    int err;
2399

2400
    if (!mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) {
2401 2402 2403
        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;
2404
            av_log(s, AV_LOG_ERROR, "could not allocate index entries\n");
2405
            return err;
2406 2407 2408
        }
    }

2409
    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
2410
        if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
2411 2412
            av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
            return -1;
2413
        }
2414
    } else if (st->codecpar->codec_id == AV_CODEC_ID_DNXHD) {
2415 2416 2417 2418
        if (!mxf_parse_dnxhd_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
            return -1;
        }
2419
    } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
2420 2421 2422 2423
        if (!mxf_parse_dv_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
            return -1;
        }
2424
    } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
2425 2426 2427 2428
        if (!mxf_parse_h264_frame(s, st, pkt, &ie)) {
            av_log(s, AV_LOG_ERROR, "could not get h264 profile\n");
            return -1;
        }
2429 2430
    }

2431 2432 2433
    if (s->oformat == &ff_mxf_opatom_muxer)
        return mxf_write_opatom_packet(s, pkt, &ie);

2434
    if (!mxf->header_written) {
2435
        if (mxf->edit_unit_byte_count) {
2436 2437
            if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0)
                return err;
2438 2439 2440
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        } else {
2441 2442
            if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0)
                return err;
2443
        }
2444 2445 2446
        mxf->header_written = 1;
    }

2447
    if (st->index == 0) {
2448 2449
        if (!mxf->edit_unit_byte_count &&
            (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) &&
2450
            !(ie.flags & 0x33)) { // I-frame, GOP start
2451
            mxf_write_klv_fill(s);
2452 2453
            if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0)
                return err;
2454 2455 2456 2457
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2458
        mxf_write_klv_fill(s);
2459
        mxf_write_system_item(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2460

2461 2462
        if (!mxf->edit_unit_byte_count) {
            mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
2463 2464
            mxf->index_entries[mxf->edit_units_count].flags = ie.flags;
            mxf->index_entries[mxf->edit_units_count].temporal_ref = ie.temporal_ref;
2465 2466
            mxf->body_offset += KAG_SIZE; // size of system element
        }
2467
        mxf->edit_units_count++;
2468
    } else if (!mxf->edit_unit_byte_count && st->index == 1) {
2469 2470 2471 2472
        if (!mxf->edit_units_count) {
            av_log(s, AV_LOG_ERROR, "No packets in first stream\n");
            return AVERROR_PATCHWELCOME;
        }
2473 2474
        mxf->index_entries[mxf->edit_units_count-1].slice_offset =
            mxf->body_offset - mxf->index_entries[mxf->edit_units_count-1].offset;
2475 2476
    }

2477
    mxf_write_klv_fill(s);
2478
    avio_write(pb, sc->track_essence_element_key, 16); // write key
2479
    if (s->oformat == &ff_mxf_d10_muxer) {
2480
        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
2481 2482 2483 2484 2485
            mxf_write_d10_video_packet(s, st, pkt);
        else
            mxf_write_d10_audio_packet(s, st, pkt);
    } else {
        klv_encode_ber4_length(pb, pkt->size); // write length
2486
        avio_write(pb, pkt->data, pkt->size);
2487 2488
        mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size);
    }
2489

2490
    avio_flush(pb);
2491

2492 2493 2494
    return 0;
}

2495 2496 2497
static void mxf_write_random_index_pack(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2498
    AVIOContext *pb = s->pb;
2499
    uint64_t pos = avio_tell(pb);
2500
    int i;
2501

2502
    avio_write(pb, random_index_pack_key, 16);
2503
    klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count);
2504

2505
    if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer)
2506
        avio_wb32(pb, 1); // BodySID of header partition
2507
    else
2508 2509
        avio_wb32(pb, 0);
    avio_wb64(pb, 0); // offset of header partition
2510

2511
    for (i = 0; i < mxf->body_partitions_count; i++) {
2512 2513
        avio_wb32(pb, 1); // BodySID
        avio_wb64(pb, mxf->body_partition_offset[i]);
2514 2515
    }

2516 2517
    avio_wb32(pb, 0); // BodySID of footer partition
    avio_wb64(pb, mxf->footer_partition_offset);
2518

2519
    avio_wb32(pb, avio_tell(pb) - pos + 4);
2520 2521
}

2522
static int mxf_write_footer(AVFormatContext *s)
2523
{
2524
    MXFContext *mxf = s->priv_data;
2525
    AVIOContext *pb = s->pb;
2526
    int err = 0;
2527

2528 2529 2530 2531 2532 2533 2534
    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;
    }

2535 2536
    mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;

2537
    mxf_write_klv_fill(s);
2538
    mxf->footer_partition_offset = avio_tell(pb);
2539
    if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { // no need to repeat index
2540
        if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0)
2541
            goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2542
    } else {
2543
        if ((err = mxf_write_partition(s, 0, 2, footer_partition_key, 0)) < 0)
2544
            goto end;
2545 2546
        mxf_write_klv_fill(s);
        mxf_write_index_table_segment(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2547
    }
2548

2549
    mxf_write_klv_fill(s);
2550 2551
    mxf_write_random_index_pack(s);

2552
    if (s->pb->seekable) {
2553 2554 2555 2556
        if (s->oformat == &ff_mxf_opatom_muxer){
            /* 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)
2557
                goto end;
2558 2559
        }

2560
        avio_seek(pb, 0, SEEK_SET);
2561
        if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) {
2562
            if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0)
2563
                goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2564 2565
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
2566
        } else {
2567
            if ((err = mxf_write_partition(s, 0, 0, header_closed_partition_key, 1)) < 0)
2568
                goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2569
        }
2570
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2571

2572
end:
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2573 2574
    ff_audio_interleave_close(s);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2575
    av_freep(&mxf->index_entries);
2576
    av_freep(&mxf->body_partition_offset);
2577 2578
    av_freep(&mxf->timecode_track->priv_data);
    av_freep(&mxf->timecode_track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2579

2580
    mxf_free(s);
2581

2582
    return err < 0 ? err : 0;
2583
}
2584

2585
static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
2586
{
2587 2588 2589 2590
    int i, stream_count = 0;

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

    if (stream_count && (s->nb_streams == stream_count || flush)) {
2593
        AVPacketList *pktl = s->internal->packet_buffer;
2594
        if (s->nb_streams != stream_count) {
2595
            AVPacketList *last = NULL;
2596
            // find last packet in edit unit
2597
            while (pktl) {
2598
                if (!stream_count || pktl->pkt.stream_index == 0)
2599
                    break;
2600
                last = pktl;
2601
                pktl = pktl->next;
2602
                stream_count--;
2603
            }
2604 2605 2606
            // purge packet queue
            while (pktl) {
                AVPacketList *next = pktl->next;
2607 2608 2609

                if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
                    s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
2610
                av_packet_unref(&pktl->pkt);
2611 2612 2613
                av_freep(&pktl);
                pktl = next;
            }
2614 2615 2616
            if (last)
                last->next = NULL;
            else {
2617 2618
                s->internal->packet_buffer = NULL;
                s->internal->packet_buffer_end= NULL;
2619
                goto out;
2620
            }
2621
            pktl = s->internal->packet_buffer;
2622 2623
        }

2624
        *out = pktl->pkt;
2625
        av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts);
2626
        s->internal->packet_buffer = pktl->next;
2627 2628
        if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
            s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
2629 2630
        if(!s->internal->packet_buffer)
            s->internal->packet_buffer_end= NULL;
2631
        av_freep(&pktl);
2632 2633
        return 1;
    } else {
2634
    out:
2635 2636 2637 2638 2639 2640 2641
        av_init_packet(out);
        return 0;
    }
}

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

2645 2646
    return next->dts > pkt->dts ||
        (next->dts == pkt->dts && sc->order < sc2->order);
2647 2648 2649 2650
}

static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
{
2651
    return ff_audio_rechunk_interleave(s, out, pkt, flush,
2652
                               mxf_interleave_get_packet, mxf_compare_timestamps);
2653 2654
}

2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
#define MXF_COMMON_OPTIONS \
    { "signal_standard", "Force/set Sigal Standard",\
      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"},



2675
static const AVOption mxf_options[] = {
2676
    MXF_COMMON_OPTIONS
2677 2678
    { "store_user_comments", "",
      offsetof(MXFContext, store_user_comments), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
2679 2680 2681 2682 2683 2684 2685 2686 2687 2688
    { NULL },
};

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

2689
static const AVOption d10_options[] = {
2690
    { "d10_channelcount", "Force/set channelcount in generic sound essence descriptor",
2691
      offsetof(MXFContext, channel_count), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 8, AV_OPT_FLAG_ENCODING_PARAM},
2692
    MXF_COMMON_OPTIONS
2693 2694
    { "store_user_comments", "",
      offsetof(MXFContext, store_user_comments), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
2695 2696 2697 2698 2699 2700 2701 2702 2703 2704
    { 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,
};

2705 2706 2707
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 },
2708
    MXF_COMMON_OPTIONS
2709 2710 2711 2712 2713 2714 2715 2716 2717 2718
    { 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,
};

2719
AVOutputFormat ff_mxf_muxer = {
2720
    .name              = "mxf",
2721
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
2722 2723 2724
    .mime_type         = "application/mxf",
    .extensions        = "mxf",
    .priv_data_size    = sizeof(MXFContext),
2725 2726
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2727 2728 2729 2730 2731
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
2732
    .priv_class        = &mxf_muxer_class,
2733
};
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2734

2735
AVOutputFormat ff_mxf_d10_muxer = {
2736
    .name              = "mxf_d10",
2737
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"),
2738 2739
    .mime_type         = "application/mxf",
    .priv_data_size    = sizeof(MXFContext),
2740 2741
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2742 2743 2744 2745 2746
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
2747
    .priv_class        = &mxf_d10_muxer_class,
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2748
};
2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762

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,
2763
    .priv_class        = &mxf_opatom_muxer_class,
2764
};