mxfenc.c 106 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 21 22 23 24 25 26 27 28
 *
 * 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
 */

/*
 * 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
29
 * SMPTE 422M Mapping JPEG 2000 Codestreams into the MXF Generic Container
30 31 32 33
 * SMPTE RP210: SMPTE Metadata Dictionary
 * SMPTE RP224: Registry of SMPTE Universal Labels
 */

34
#include <inttypes.h>
35
#include <math.h>
36
#include <time.h>
37

38
#include "libavutil/opt.h"
39
#include "libavutil/random_seed.h"
40
#include "libavutil/timecode.h"
41
#include "libavutil/avassert.h"
42
#include "libavutil/pixdesc.h"
43
#include "libavutil/time_internal.h"
44
#include "libavcodec/bytestream.h"
45
#include "libavcodec/dnxhddata.h"
46 47
#include "libavcodec/h264.h"
#include "libavcodec/internal.h"
48
#include "audiointerleave.h"
49
#include "avformat.h"
Paul B Mahol's avatar
Paul B Mahol committed
50
#include "avio_internal.h"
51
#include "internal.h"
52
#include "mxf.h"
53
#include "config.h"
54

55
extern AVOutputFormat ff_mxf_d10_muxer;
56
extern AVOutputFormat ff_mxf_opatom_muxer;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
57

58
#define EDIT_UNITS_PER_BODY 250
59
#define KAG_SIZE 512
60

61
typedef struct MXFLocalTagPair {
62 63 64 65
    int local_tag;
    UID uid;
} MXFLocalTagPair;

66
typedef struct MXFIndexEntry {
67 68
    uint8_t flags;
    uint64_t offset;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
69
    unsigned slice_offset; ///< offset of audio slice
70
    uint16_t temporal_ref;
71 72
} MXFIndexEntry;

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

91
typedef struct MXFContainerEssenceEntry {
92 93
    UID container_ul;
    UID element_ul;
94
    UID codec_ul;
95
    void (*write_desc)(AVFormatContext *, AVStream *);
96
} MXFContainerEssenceEntry;
97

98
static const struct {
99
    enum AVCodecID id;
100 101
    int index;
} mxf_essence_mappings[] = {
102 103 104
    { AV_CODEC_ID_MPEG2VIDEO, 0 },
    { AV_CODEC_ID_PCM_S24LE,  1 },
    { AV_CODEC_ID_PCM_S16LE,  1 },
105 106
    { AV_CODEC_ID_DVVIDEO,   15 },
    { AV_CODEC_ID_DNXHD,     24 },
107
    { AV_CODEC_ID_JPEG2000,  34 },
108
    { AV_CODEC_ID_H264,      35 },
109
    { AV_CODEC_ID_NONE }
110 111
};

112
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st);
113
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st);
114
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
115 116
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
117

118
static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
119
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 },
120
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
121
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
122
      mxf_write_mpegvideo_desc },
123 124 125
    { { 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 },
126
      mxf_write_aes3_desc },
127
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 },
128
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x16,0x01,0x01,0x00 },
129
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
130
      mxf_write_wav_desc },
Baptiste Coudurier's avatar
Baptiste Coudurier committed
131 132 133 134 135 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
    // 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 },
185
    // DV Unknown
186 187 188 189 190 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
    { { 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 },
230 231 232
    // 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 },
233
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 },
234 235 236 237
      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 },
238
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 },
239 240 241 242
      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 },
243
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 },
244 245 246 247
      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 },
248
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 },
249 250 251 252
      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 },
253
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 },
254 255 256 257
      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 },
258
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 },
259 260 261 262
      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 },
263
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 },
264 265 266 267
      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 },
268
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 },
269 270 271 272
      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 },
273
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 },
274 275 276 277
      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 },
278
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 },
279
      mxf_write_cdci_desc },
280 281 282 283 284
    // 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 },
285 286 287 288 289
    // 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 },
290
    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
291
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
292
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
293
      NULL },
294 295
};

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

324
static const uint8_t uuid_base[]            = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
325
static const uint8_t umid_ul[]              = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 };
326 327 328 329

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

341 342 343 344
/**
 * 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 };
345
static const uint8_t multiple_desc_ul[]     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x0D,0x01,0x03,0x01,0x02,0x7F,0x01,0x00 };
346

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

447
static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value)
448
{
449 450 451
    avio_write(pb, uuid_base, 12);
    avio_wb16(pb, type);
    avio_wb16(pb, value);
452 453
}

454
static void mxf_write_umid(AVFormatContext *s, int type)
455
{
456
    MXFContext *mxf = s->priv_data;
457 458 459 460
    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);
461
}
462

463
static void mxf_write_refs_count(AVIOContext *pb, int ref_count)
464
{
465 466
    avio_wb32(pb, ref_count);
    avio_wb32(pb, 16);
467 468
}

469 470 471 472 473 474 475 476
static int klv_ber_length(uint64_t len)
{
    if (len < 128)
        return 1;
    else
        return (av_log2(len) >> 3) + 2;
}

477
static int klv_encode_ber_length(AVIOContext *pb, uint64_t len)
478 479 480 481 482
{
    // Determine the best BER size
    int size;
    if (len < 128) {
        //short form
483
        avio_w8(pb, len);
484 485 486 487 488 489
        return 1;
    }

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

    // long form
490
    avio_w8(pb, 0x80 + size);
491
    while(size) {
492
        size--;
493
        avio_w8(pb, len >> 8 * size & 0xff);
494 495 496 497
    }
    return 0;
}

498
static void klv_encode_ber4_length(AVIOContext *pb, int len)
499
{
500 501
    avio_w8(pb, 0x80 + 3);
    avio_wb24(pb, len);
502 503
}

504 505 506 507 508 509
static void klv_encode_ber9_length(AVIOContext *pb, uint64_t len)
{
    avio_w8(pb, 0x80 + 8);
    avio_wb64(pb, len);
}

510
/*
511
 * Get essence container ul index
512
 */
513
static int mxf_get_essence_container_ul_index(enum AVCodecID id)
514
{
515
    int i;
516 517 518
    for (i = 0; mxf_essence_mappings[i].id; i++)
        if (mxf_essence_mappings[i].id == id)
            return mxf_essence_mappings[i].index;
519
    return -1;
520 521
}

522
static void mxf_write_primer_pack(AVFormatContext *s)
523
{
524
    AVIOContext *pb = s->pb;
525 526
    int local_tag_number, i = 0;

527
    local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch);
528

529
    avio_write(pb, primer_pack_key, 16);
530 531
    klv_encode_ber_length(pb, local_tag_number * 18 + 8);

532 533
    avio_wb32(pb, local_tag_number); // local_tag num
    avio_wb32(pb, 18); // item size, always 18 according to the specs
534 535

    for (i = 0; i < local_tag_number; i++) {
536 537
        avio_wb16(pb, mxf_local_tag_batch[i].local_tag);
        avio_write(pb, mxf_local_tag_batch[i].uid, 16);
538 539 540
    }
}

541
static void mxf_write_local_tag(AVIOContext *pb, int size, int tag)
542
{
543 544
    avio_wb16(pb, tag);
    avio_wb16(pb, size);
545 546
}

547
static void mxf_write_metadata_key(AVIOContext *pb, unsigned int value)
548
{
549 550
    avio_write(pb, header_metadata_key, 13);
    avio_wb24(pb, value);
551 552
}

553 554 555 556 557
static void mxf_free(AVFormatContext *s)
{
    int i;

    for (i = 0; i < s->nb_streams; i++) {
558
        AVStream *st = s->streams[i];
559 560 561 562
        av_freep(&st->priv_data);
    }
}

563
static const MXFCodecUL *mxf_get_data_definition_ul(int type)
564
{
565 566 567
    const MXFCodecUL *uls = ff_mxf_data_definition_uls;
    while (uls->uid[0]) {
        if (type == uls->id)
568
            break;
569
        uls++;
570 571 572 573
    }
    return uls;
}

574 575 576 577
//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)

578
static void mxf_write_essence_container_refs(AVFormatContext *s)
579
{
580
    MXFContext *c = s->priv_data;
581
    AVIOContext *pb = s->pb;
582
    int i;
583

584
    mxf_write_refs_count(pb, DESCRIPTOR_COUNT(c->essence_container_count));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
585 586
    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
587
        MXFStreamContext *sc = s->streams[i]->priv_data;
588
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
589
    }
590 591 592

    if (c->essence_container_count > 1)
        avio_write(pb, multiple_desc_ul, 16);
593 594
}

595 596 597
static void mxf_write_preface(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
598
    AVIOContext *pb = s->pb;
599 600 601

    mxf_write_metadata_key(pb, 0x012f00);
    PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
602
    klv_encode_ber_length(pb, 130 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
603 604 605 606 607 608

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

609
    // last modified date
610
    mxf_write_local_tag(pb, 8, 0x3B02);
611
    avio_wb64(pb, mxf->timestamp);
612 613 614

    // write version
    mxf_write_local_tag(pb, 2, 0x3B05);
615
    avio_wb16(pb, 258); // v1.2
616 617 618 619 620 621 622 623 624 625

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

626
    // operational pattern
627
    mxf_write_local_tag(pb, 16, 0x3B09);
628 629 630 631
    if (s->oformat == &ff_mxf_opatom_muxer)
        avio_write(pb, opatom_ul, 16);
    else
        avio_write(pb, op1a_ul, 16);
632 633

    // write essence_container_refs
634
    mxf_write_local_tag(pb, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A);
635
    mxf_write_essence_container_refs(s);
636 637 638

    // write dm_scheme_refs
    mxf_write_local_tag(pb, 8, 0x3B0B);
639
    avio_wb64(pb, 0);
640 641
}

642
/*
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
 * 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:
        av_log(NULL, AV_LOG_ERROR, "Invaid UTF8 sequence in mxf_utf16len\n\n");
    }
    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
686
 */
687
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
688
{
689 690 691 692 693 694 695
    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;
    }

696
    mxf_write_local_tag(pb, size*2, tag);
697
    avio_put_str16be(pb, value);
698 699
}

700 701
static void mxf_write_identification(AVFormatContext *s)
{
702
    MXFContext *mxf = s->priv_data;
703
    AVIOContext *pb = s->pb;
704
    const char *company = "FFmpeg";
705
    const char *product = s->oformat != &ff_mxf_opatom_muxer ? "OP1a Muxer" : "OPAtom Muxer";
706
    const char *version;
707
    int length;
708 709 710 711

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

712
    version = s->flags & AVFMT_FLAG_BITEXACT ?
713
        "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
714 715 716
    length = 72 + mxf_utf16_local_tag_length(company) +
                  mxf_utf16_local_tag_length(product) +
                  mxf_utf16_local_tag_length(version);
717 718 719 720 721 722
    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
723

724 725 726
    // write generation uid
    mxf_write_local_tag(pb, 16, 0x3C09);
    mxf_write_uuid(pb, Identification, 1);
727 728
    mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
    mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
729
    mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
730 731 732 733 734

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

735
    // modification date
736
    mxf_write_local_tag(pb, 8, 0x3C06);
737
    avio_wb64(pb, mxf->timestamp);
738 739 740 741
}

static void mxf_write_content_storage(AVFormatContext *s)
{
742
    AVIOContext *pb = s->pb;
743 744 745

    mxf_write_metadata_key(pb, 0x011800);
    PRINT_KEY(s, "content storage key", pb->buf_ptr - 16);
746
    klv_encode_ber_length(pb, 92);
747 748 749 750 751

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

753 754 755 756 757
    // 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);
758 759 760 761 762

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

765
static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
766
{
767
    MXFContext *mxf = s->priv_data;
768
    AVIOContext *pb = s->pb;
769
    MXFStreamContext *sc = st->priv_data;
770 771 772 773 774 775 776

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

780 781
    // write track id
    mxf_write_local_tag(pb, 4, 0x4801);
782
    avio_wb32(pb, st->index+2);
783

784
    // write track number
785
    mxf_write_local_tag(pb, 4, 0x4804);
786
    if (type == MaterialPackage)
787
        avio_wb32(pb, 0); // track number of material package is 0
788
    else
789
        avio_write(pb, sc->track_essence_element_key + 12, 4);
790 791

    mxf_write_local_tag(pb, 8, 0x4B01);
792 793 794 795 796 797 798 799

    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);
    }
800 801 802

    // write origin
    mxf_write_local_tag(pb, 8, 0x4B02);
803
    avio_wb64(pb, 0);
804 805 806

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

810 811 812
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)
813
{
814
    MXFContext *mxf = s->priv_data;
815
    AVIOContext *pb = s->pb;
816

817 818
    // find data define uls
    mxf_write_local_tag(pb, 16, 0x0201);
819
    if (st == mxf->timecode_track)
820
        avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
821 822
    else {
        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
823
        avio_write(pb, data_def_ul->uid, 16);
824
    }
825 826 827

    // write duration
    mxf_write_local_tag(pb, 8, 0x0202);
828 829 830 831 832 833

    if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
        avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count);
    } else {
        avio_wb64(pb, mxf->duration);
    }
834 835
}

836
static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
837
{
838
    MXFContext *mxf = s->priv_data;
839
    AVIOContext *pb = s->pb;
840
    enum MXFMetadataSetType component;
841 842 843 844 845 846

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

    PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
850
    mxf_write_common_fields(s, st);
851 852 853 854

    // write structural component
    mxf_write_local_tag(pb, 16 + 8, 0x1001);
    mxf_write_refs_count(pb, 1);
855 856 857
    if (st == mxf->timecode_track)
        component = TimecodeComponent;
    else
858 859 860
        component = SourceClip;
    if (type == SourcePackage)
        component += TypeBottom;
861 862 863
    mxf_write_uuid(pb, component, st->index);
}

864
static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
865 866
{
    MXFContext *mxf = s->priv_data;
867
    AVIOContext *pb = s->pb;
868 869 870 871 872 873

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

    // UID
    mxf_write_local_tag(pb, 16, 0x3C0A);
874 875
    mxf_write_uuid(pb, type == MaterialPackage ? TimecodeComponent :
                   TimecodeComponent + TypeBottom, st->index);
876 877 878 879 880

    mxf_write_common_fields(s, st);

    // Start Time Code
    mxf_write_local_tag(pb, 8, 0x1501);
881
    avio_wb64(pb, mxf->tc.start);
882 883 884

    // Rounded Time Code Base
    mxf_write_local_tag(pb, 2, 0x1502);
885
    avio_wb16(pb, mxf->timecode_base);
886 887 888

    // Drop Frame
    mxf_write_local_tag(pb, 1, 0x1503);
889
    avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
890 891
}

892
static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
893
{
894
    AVIOContext *pb = s->pb;
895 896 897 898 899 900 901 902
    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);
903
    mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index);
904 905

    PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
906
    mxf_write_common_fields(s, st);
907 908 909

    // write start_position
    mxf_write_local_tag(pb, 8, 0x1201);
910
    avio_wb64(pb, 0);
911

912
    // write source package uid, end of the reference
913 914
    mxf_write_local_tag(pb, 32, 0x1101);
    if (type == SourcePackage) {
915
        for (i = 0; i < 4; i++)
916
            avio_wb64(pb, 0);
917
    } else
918
        mxf_write_umid(s, 1);
919

920
    // write source track id
921 922
    mxf_write_local_tag(pb, 4, 0x1102);
    if (type == SourcePackage)
923
        avio_wb32(pb, 0);
924
    else
925
        avio_wb32(pb, st->index+2);
926 927
}

928 929
static void mxf_write_multi_descriptor(AVFormatContext *s)
{
930
    MXFContext *mxf = s->priv_data;
931
    AVIOContext *pb = s->pb;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
932
    const uint8_t *ul;
933 934 935 936
    int i;

    mxf_write_metadata_key(pb, 0x014400);
    PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16);
937
    klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams);
938 939 940 941 942 943 944

    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);
945 946
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
947 948 949

    // write essence container ul
    mxf_write_local_tag(pb, 16, 0x3004);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
950 951
    if (mxf->essence_container_count > 1)
        ul = multiple_desc_ul;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
952 953 954 955
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
        ul = mxf_essence_container_uls[sc->index].container_ul;
    }
956
    avio_write(pb, ul, 16);
957 958 959 960

    // write sub descriptor refs
    mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01);
    mxf_write_refs_count(pb, s->nb_streams);
961
    for (i = 0; i < s->nb_streams; i++)
962 963 964
        mxf_write_uuid(pb, SubDescriptor, i);
}

965
static void mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
966
{
967
    MXFContext *mxf = s->priv_data;
968
    MXFStreamContext *sc = st->priv_data;
969
    AVIOContext *pb = s->pb;
970

971
    avio_write(pb, key, 16);
972
    klv_encode_ber4_length(pb, size+20+8+12+20);
973 974 975 976 977

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

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

980
    mxf_write_local_tag(pb, 8, 0x3001);
981 982
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
983

984
    mxf_write_local_tag(pb, 16, 0x3004);
985
    avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
986 987
}

988 989
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 };
990
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
991 992
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 };
993

994
static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
995
{
996
    MXFStreamContext *sc = st->priv_data;
997
    AVIOContext *pb = s->pb;
998
    int stored_height = (st->codec->height+15)/16*16;
999
    int display_height;
1000
    int f1, f2;
1001
    unsigned desc_size = size+8+8+8+8+8+8+8+5+16+sc->interlaced*4+12+20+5;
1002 1003
    if (sc->interlaced && sc->field_dominance)
        desc_size += 5;
1004 1005
    if (sc->signal_standard)
        desc_size += 5;
1006

1007
    mxf_write_generic_desc(s, st, key, desc_size);
1008 1009

    mxf_write_local_tag(pb, 4, 0x3203);
1010
    avio_wb32(pb, st->codec->width);
1011 1012

    mxf_write_local_tag(pb, 4, 0x3202);
1013
    avio_wb32(pb, stored_height>>sc->interlaced);
1014

1015
    mxf_write_local_tag(pb, 4, 0x3209);
1016
    avio_wb32(pb, st->codec->width);
1017

1018 1019 1020 1021 1022 1023 1024
    if (st->codec->height == 608) // PAL + VBI
        display_height = 576;
    else if (st->codec->height == 512)  // NTSC + VBI
        display_height = 486;
    else
        display_height = st->codec->height;

1025
    mxf_write_local_tag(pb, 4, 0x3208);
1026
    avio_wb32(pb, display_height>>sc->interlaced);
1027

1028 1029 1030 1031
    // presentation Y offset
    mxf_write_local_tag(pb, 4, 0x320B);
    avio_wb32(pb, (st->codec->height - display_height)>>sc->interlaced);

1032 1033
    // component depth
    mxf_write_local_tag(pb, 4, 0x3301);
1034
    avio_wb32(pb, sc->component_depth);
1035 1036 1037

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

1040 1041 1042 1043
    // color siting
    mxf_write_local_tag(pb, 1, 0x3303);
    avio_w8(pb, sc->color_siting);

1044 1045 1046 1047 1048
    if (sc->signal_standard) {
        mxf_write_local_tag(pb, 1, 0x3215);
        avio_w8(pb, sc->signal_standard);
    }

1049 1050
    // frame layout
    mxf_write_local_tag(pb, 1, 0x320C);
1051
    avio_w8(pb, sc->interlaced);
1052

1053 1054
    // video line map
    switch (st->codec->height) {
1055
    case  576: f1 = 23; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
1056
    case  608: f1 =  7; f2 = 320; break;
1057
    case  480: f1 = 20; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
    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;
    }

1069
    mxf_write_local_tag(pb, 12+sc->interlaced*4, 0x320D);
1070 1071 1072
    avio_wb32(pb, sc->interlaced ? 2 : 1);
    avio_wb32(pb, 4);
    avio_wb32(pb, f1);
1073
    if (sc->interlaced)
1074
        avio_wb32(pb, f2);
1075

1076
    mxf_write_local_tag(pb, 8, 0x320E);
1077 1078
    avio_wb32(pb, sc->aspect_ratio.num);
    avio_wb32(pb, sc->aspect_ratio.den);
1079 1080

    mxf_write_local_tag(pb, 16, 0x3201);
1081
    avio_write(pb, *sc->codec_ul, 16);
1082 1083 1084 1085 1086 1087

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

1088 1089
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1090 1091
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
{
1092
    mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1093 1094
}

1095 1096
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
{
1097
    AVIOContext *pb = s->pb;
1098
    MXFStreamContext *sc = st->priv_data;
1099
    int profile_and_level = (st->codec->profile<<4) | st->codec->level;
1100

1101
    if (st->codec->codec_id != AV_CODEC_ID_H264) {
1102
        mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5);
1103

1104 1105 1106
        // bit rate
        mxf_write_local_tag(pb, 4, 0x8000);
        avio_wb32(pb, sc->video_bit_rate);
1107

1108 1109 1110 1111 1112
        // profile and level
        mxf_write_local_tag(pb, 1, 0x8007);
        if (!st->codec->profile)
            profile_and_level |= 0x80; // escape bit
        avio_w8(pb, profile_and_level);
1113 1114 1115
    } else {
        mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 0);
    }
1116 1117 1118
}

static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1119
{
1120
    AVIOContext *pb = s->pb;
1121 1122
    MXFContext *mxf = s->priv_data;
    int show_warnings = !mxf->footer_partition_offset;
1123 1124 1125 1126
    int duration_size = 0;

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

1128 1129 1130 1131 1132 1133
    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);
    }
1134

1135
    // audio locked
1136
    mxf_write_local_tag(pb, 1, 0x3D02);
1137
    avio_w8(pb, 1);
1138 1139 1140

    // write audio sampling rate
    mxf_write_local_tag(pb, 8, 0x3D03);
1141 1142
    avio_wb32(pb, st->codec->sample_rate);
    avio_wb32(pb, 1);
1143 1144

    mxf_write_local_tag(pb, 4, 0x3D07);
1145 1146
    if (mxf->channel_count == -1) {
        if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codec->channels != 4) && (st->codec->channels != 8))
1147
            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");
1148 1149 1150
        avio_wb32(pb, st->codec->channels);
    } else if (s->oformat == &ff_mxf_d10_muxer) {
        if (show_warnings && (mxf->channel_count < st->codec->channels))
1151
            av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n");
1152
        if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8))
1153
            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");
1154 1155
        avio_wb32(pb, mxf->channel_count);
    } else {
1156
        if (show_warnings && mxf->channel_count != -1 && s->oformat != &ff_mxf_opatom_muxer)
1157
            av_log(s, AV_LOG_ERROR, "-d10_channelcount requires MXF D-10 and will be ignored\n");
1158 1159
        avio_wb32(pb, st->codec->channels);
    }
1160 1161

    mxf_write_local_tag(pb, 4, 0x3D01);
1162
    avio_wb32(pb, av_get_bits_per_sample(st->codec->codec_id));
1163 1164
}

1165
static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1166
{
1167
    AVIOContext *pb = s->pb;
1168

1169
    mxf_write_generic_sound_common(s, st, key, size+6+8);
1170 1171

    mxf_write_local_tag(pb, 2, 0x3D0A);
1172
    avio_wb16(pb, st->codec->block_align);
1173 1174 1175

    // avg bytes per sec
    mxf_write_local_tag(pb, 4, 0x3D09);
1176
    avio_wb32(pb, st->codec->block_align*st->codec->sample_rate);
1177 1178
}

1179
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st)
1180
{
1181
    mxf_write_wav_common(s, st, mxf_wav_descriptor_key, 0);
1182
}
1183

1184 1185
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st)
{
1186
    mxf_write_wav_common(s, st, mxf_aes3_descriptor_key, 0);
1187 1188
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1189 1190
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st)
{
1191
    mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1192 1193
}

1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 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
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;
}

1243
static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, const char *package_name)
1244
{
1245
    MXFContext *mxf = s->priv_data;
1246
    AVIOContext *pb = s->pb;
1247
    int i, track_count = s->nb_streams+1;
1248
    int name_size = mxf_utf16_local_tag_length(package_name);
1249
    int user_comment_count = 0;
1250 1251

    if (type == MaterialPackage) {
1252
        user_comment_count = mxf_write_user_comments(s, s->metadata);
1253 1254
        mxf_write_metadata_key(pb, 0x013600);
        PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
1255
        klv_encode_ber_length(pb, 104 + name_size + (16*track_count) + (16*user_comment_count));
1256 1257 1258
    } else {
        mxf_write_metadata_key(pb, 0x013700);
        PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
1259
        klv_encode_ber_length(pb, 124 + name_size + (16*track_count)); // 20 bytes length for descriptor reference
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
    }

    // 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);
1270
    mxf_write_umid(s, type == SourcePackage);
1271 1272
    PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16);

1273 1274 1275 1276
    // package name
    if (name_size)
        mxf_write_local_tag_utf16(pb, 0x4402, package_name);

1277
    // package creation date
1278
    mxf_write_local_tag(pb, 8, 0x4405);
1279
    avio_wb64(pb, mxf->timestamp);
1280

1281
    // package modified date
1282
    mxf_write_local_tag(pb, 8, 0x4404);
1283
    avio_wb64(pb, mxf->timestamp);
1284 1285

    // write track refs
1286 1287
    mxf_write_local_tag(pb, track_count*16 + 8, 0x4403);
    mxf_write_refs_count(pb, track_count);
1288 1289
    mxf_write_uuid(pb, type == MaterialPackage ? Track :
                   Track + TypeBottom, -1); // timecode track
1290 1291 1292
    for (i = 0; i < s->nb_streams; i++)
        mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, i);

1293 1294 1295 1296 1297 1298
    // write user comment refs
    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);

1299 1300 1301
    // write multiple descriptor reference
    if (type == SourcePackage) {
        mxf_write_local_tag(pb, 16, 0x4701);
1302 1303 1304 1305 1306
        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
1307
    }
1308

1309 1310 1311 1312 1313
    // 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);

1314
    for (i = 0; i < s->nb_streams; i++) {
1315 1316 1317 1318
        AVStream *st = s->streams[i];
        mxf_write_track(s, st, type);
        mxf_write_sequence(s, st, type);
        mxf_write_structural_component(s, st, type);
1319 1320

        if (type == SourcePackage) {
1321
            MXFStreamContext *sc = st->priv_data;
1322
            mxf_essence_container_uls[sc->index].write_desc(s, st);
1323 1324 1325 1326
        }
    }
}

1327 1328
static int mxf_write_essence_container_data(AVFormatContext *s)
{
1329
    AVIOContext *pb = s->pb;
1330 1331

    mxf_write_metadata_key(pb, 0x012300);
1332
    klv_encode_ber_length(pb, 72);
1333 1334 1335 1336 1337

    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
1338
    mxf_write_umid(s, 1);
1339 1340

    mxf_write_local_tag(pb, 4, 0x3F07); // BodySID
1341
    avio_wb32(pb, 1);
1342

1343
    mxf_write_local_tag(pb, 4, 0x3F06); // IndexSID
1344
    avio_wb32(pb, 2);
1345

1346 1347 1348
    return 0;
}

1349 1350
static int mxf_write_header_metadata_sets(AVFormatContext *s)
{
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
    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;
            }
        }
    }

1373
    mxf_write_preface(s);
1374 1375
    mxf_write_identification(s);
    mxf_write_content_storage(s);
1376 1377
    mxf_write_package(s, MaterialPackage, material_package_name);
    mxf_write_package(s, SourcePackage, file_package_name);
1378
    mxf_write_essence_container_data(s);
1379 1380 1381
    return 0;
}

1382
static unsigned klv_fill_size(uint64_t size)
1383
{
1384
    unsigned pad = KAG_SIZE - (size & (KAG_SIZE-1));
1385
    if (pad < 20) // smallest fill item possible
1386 1387 1388 1389 1390
        return pad + KAG_SIZE;
    else
        return pad & (KAG_SIZE-1);
}

1391
static void mxf_write_index_table_segment(AVFormatContext *s)
1392 1393
{
    MXFContext *mxf = s->priv_data;
1394
    AVIOContext *pb = s->pb;
1395
    int i, j, temporal_reordering = 0;
1396
    int key_index = mxf->last_key_index;
1397 1398 1399

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1400
    if (!mxf->edit_units_count && !mxf->edit_unit_byte_count)
1401 1402
        return;

1403
    avio_write(pb, index_table_segment_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1404 1405

    if (mxf->edit_unit_byte_count) {
1406
        klv_encode_ber_length(pb, 80);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1407
    } else {
1408 1409
        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
1410
    }
1411 1412 1413 1414 1415 1416 1417

    // 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);
1418 1419
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
1420 1421 1422

    // index start position
    mxf_write_local_tag(pb, 8, 0x3F0C);
1423
    avio_wb64(pb, mxf->last_indexed_edit_unit);
1424 1425 1426

    // index duration
    mxf_write_local_tag(pb, 8, 0x3F0D);
1427
    if (mxf->edit_unit_byte_count)
1428
        avio_wb64(pb, 0); // index table covers whole container
1429
    else
1430
        avio_wb64(pb, mxf->edit_units_count);
1431 1432 1433

    // edit unit byte count
    mxf_write_local_tag(pb, 4, 0x3F05);
1434
    avio_wb32(pb, mxf->edit_unit_byte_count);
1435 1436 1437

    // index sid
    mxf_write_local_tag(pb, 4, 0x3F06);
1438
    avio_wb32(pb, 2);
1439 1440 1441

    // body sid
    mxf_write_local_tag(pb, 4, 0x3F07);
1442
    avio_wb32(pb, 1);
1443

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1444
    if (!mxf->edit_unit_byte_count) {
1445 1446
        // real slice count - 1
        mxf_write_local_tag(pb, 1, 0x3F08);
1447
        avio_w8(pb, mxf->slice_count);
1448

1449 1450
        // delta entry array
        mxf_write_local_tag(pb, 8 + (s->nb_streams+1)*6, 0x3F09);
1451 1452
        avio_wb32(pb, s->nb_streams+1); // num of entries
        avio_wb32(pb, 6);               // size of one entry
1453
        // write system item delta entry
1454 1455 1456
        avio_w8(pb, 0);
        avio_w8(pb, 0); // slice entry
        avio_wb32(pb, 0); // element delta
1457 1458 1459
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            MXFStreamContext *sc = st->priv_data;
1460
            avio_w8(pb, sc->temporal_reordering);
1461 1462 1463
            if (sc->temporal_reordering)
                temporal_reordering = 1;
            if (i == 0) { // video track
1464 1465
                avio_w8(pb, 0); // slice number
                avio_wb32(pb, KAG_SIZE); // system item size including klv fill
1466 1467 1468
            } else { // audio track
                unsigned audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
                audio_frame_size += klv_fill_size(audio_frame_size);
1469 1470
                avio_w8(pb, 1);
                avio_wb32(pb, (i-1)*audio_frame_size); // element delta
1471
            }
1472
        }
1473

1474
        mxf_write_local_tag(pb, 8 + mxf->edit_units_count*(11+mxf->slice_count*4), 0x3F0A);
1475 1476
        avio_wb32(pb, mxf->edit_units_count);  // num of entries
        avio_wb32(pb, 11+mxf->slice_count*4);  // size of one entry
1477

1478
        for (i = 0; i < mxf->edit_units_count; i++) {
1479
            int temporal_offset = 0;
1480 1481 1482 1483 1484 1485

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

1486
            if (temporal_reordering) {
1487 1488 1489 1490 1491
                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;
1492
                    }
1493 1494 1495
                    if (j == mxf->edit_units_count)
                        av_log(s, AV_LOG_WARNING, "missing frames\n");
                    temporal_offset = j - key_index - pic_num_in_gop;
1496
                }
1497
            }
1498
            avio_w8(pb, temporal_offset);
1499 1500

            if ((mxf->index_entries[i].flags & 0x30) == 0x30) { // back and forward prediction
1501
                avio_w8(pb, mxf->last_key_index - i);
1502
            } else {
1503
                avio_w8(pb, key_index - i); // key frame offset
1504 1505 1506
                if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward
                    mxf->last_key_index = key_index;
            }
1507 1508 1509 1510

            if (!(mxf->index_entries[i].flags & 0x33) && // I frame
                mxf->index_entries[i].flags & 0x40 && !temporal_offset)
                mxf->index_entries[i].flags |= 0x80; // random access
1511
            avio_w8(pb, mxf->index_entries[i].flags);
1512
            // stream offset
1513
            avio_wb64(pb, mxf->index_entries[i].offset);
1514
            if (s->nb_streams > 1)
1515
                avio_wb32(pb, mxf->index_entries[i].slice_offset);
1516
        }
1517

1518 1519 1520
        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
1521
    }
1522 1523
}

1524 1525
static void mxf_write_klv_fill(AVFormatContext *s)
{
1526
    unsigned pad = klv_fill_size(avio_tell(s->pb));
1527
    if (pad) {
1528
        avio_write(s->pb, klv_fill_key, 16);
1529 1530
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
1531
        ffio_fill(s->pb, 0, pad);
1532
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
1533 1534 1535
    }
}

1536
static int mxf_write_partition(AVFormatContext *s, int bodysid,
1537
                                int indexsid,
1538
                                const uint8_t *key, int write_metadata)
1539 1540
{
    MXFContext *mxf = s->priv_data;
1541
    AVIOContext *pb = s->pb;
1542
    int64_t header_byte_count_offset;
1543
    unsigned index_byte_count = 0;
1544
    uint64_t partition_offset = avio_tell(pb);
1545
    int err;
1546

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1547 1548 1549 1550
    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)
1551
        index_byte_count = 80;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1552 1553

    if (index_byte_count) {
1554 1555 1556
        // add encoded ber length
        index_byte_count += 16 + klv_ber_length(index_byte_count);
        index_byte_count += klv_fill_size(index_byte_count);
1557 1558
    }

1559
    if (key && !memcmp(key, body_partition_key, 16)) {
1560 1561 1562 1563 1564
        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;
        }
1565
        mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset;
1566
    }
1567

1568
    // write klv
1569 1570 1571 1572 1573
    if (key)
        avio_write(pb, key, 16);
    else
        avio_write(pb, body_partition_key, 16);

1574
    klv_encode_ber_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
1575 1576

    // write partition value
1577 1578 1579
    avio_wb16(pb, 1); // majorVersion
    avio_wb16(pb, 2); // minorVersion
    avio_wb32(pb, KAG_SIZE); // KAGSize
1580

1581
    avio_wb64(pb, partition_offset); // ThisPartition
1582

1583
    if (key && !memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
1584
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition
1585
    else if (key && !memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
1586
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
1587
    else
1588
        avio_wb64(pb, 0);
1589

1590
    avio_wb64(pb, mxf->footer_partition_offset); // footerPartition
1591 1592

    // set offset
1593
    header_byte_count_offset = avio_tell(pb);
1594
    avio_wb64(pb, 0); // headerByteCount, update later
1595

1596
    // indexTable
1597 1598
    avio_wb64(pb, index_byte_count); // indexByteCount
    avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
1599 1600

    // BodyOffset
1601
    if (bodysid && mxf->edit_units_count && mxf->body_partitions_count && s->oformat != &ff_mxf_opatom_muxer)
1602
        avio_wb64(pb, mxf->body_offset);
1603
    else
1604
        avio_wb64(pb, 0);
1605

1606
    avio_wb32(pb, bodysid); // bodySID
1607 1608

    // operational pattern
1609 1610 1611 1612
    if (s->oformat == &ff_mxf_opatom_muxer)
        avio_write(pb, opatom_ul, 16);
    else
        avio_write(pb, op1a_ul, 16);
1613 1614

    // essence container
1615
    mxf_write_essence_container_refs(s);
1616 1617 1618

    if (write_metadata) {
        // mark the start of the headermetadata and calculate metadata size
1619
        int64_t pos, start;
1620 1621
        unsigned header_byte_count;

1622
        mxf_write_klv_fill(s);
1623
        start = avio_tell(s->pb);
1624 1625
        mxf_write_primer_pack(s);
        mxf_write_header_metadata_sets(s);
1626
        pos = avio_tell(s->pb);
1627
        header_byte_count = pos - start + klv_fill_size(pos);
1628

1629
        // update header_byte_count
1630
        avio_seek(pb, header_byte_count_offset, SEEK_SET);
1631
        avio_wb64(pb, header_byte_count);
1632
        avio_seek(pb, pos, SEEK_SET);
1633 1634
    }

1635 1636
    if(key)
        avio_flush(pb);
1637 1638

    return 0;
1639 1640
}

1641 1642 1643 1644 1645 1646 1647
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;
1648
    int frame_size = 0;
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658

    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];

1659
    if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) < 0)
1660
        return -1;
1661 1662
    if ((sc->interlaced = avpriv_dnxhd_get_interlaced(cid)) < 0)
        return AVERROR_INVALIDDATA;
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701

    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;
    }

1702 1703
    sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
    sc->aspect_ratio = (AVRational){ 16, 9 };
1704

1705 1706 1707 1708 1709
    if(s->oformat == &ff_mxf_opatom_muxer){
        mxf->edit_unit_byte_count = frame_size;
        return 1;
    }

1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725
    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;
        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            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);
        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            mxf->edit_unit_byte_count += 16 + 4 + frame_size;
            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
        }
    }

    return 1;
}

1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
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) {
1760
            av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n");
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779
            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;

1780 1781 1782 1783 1784
    if(s->oformat == &ff_mxf_opatom_muxer) {
        mxf->edit_unit_byte_count = frame_size;
        return 1;
    }

1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
    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;
        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            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);
        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            mxf->edit_unit_byte_count += 16 + 4 + frame_size;
            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
        }
    }

    return 1;
}

1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
static const struct {
    UID uid;
    int frame_size;
    int profile;
    uint8_t interlaced;
} mxf_h264_codec_uls[] = {
    {{ 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) {
        case NAL_SPS:
            st->codec->profile = buf[1];
            e->flags |= 0x40;
            break;
        case NAL_PPS:
            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
    sc->interlaced = st->codec->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
    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;
        } else if (st->codec->profile == mxf_h264_codec_uls[i].profile) {
            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;
}

1890 1891 1892 1893 1894 1895 1896 1897 1898
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
1899 1900
    { 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
1901 1902 1903 1904
};

static const UID *mxf_get_mpeg2_codec_ul(AVCodecContext *avctx)
{
1905 1906
    int long_gop = avctx->gop_size > 1 || avctx->has_b_frames;

1907 1908
    if (avctx->profile == 4) { // Main
        if (avctx->level == 8) // Main
1909
            return &mxf_mpeg2_codec_uls[0+long_gop];
1910
        else if (avctx->level == 4) // High
1911
            return &mxf_mpeg2_codec_uls[4+long_gop];
1912 1913
        else if (avctx->level == 6) // High 14
            return &mxf_mpeg2_codec_uls[8+long_gop];
1914 1915
    } else if (avctx->profile == 0) { // 422
        if (avctx->level == 5) // Main
1916
            return &mxf_mpeg2_codec_uls[2+long_gop];
1917
        else if (avctx->level == 2) // High
1918
            return &mxf_mpeg2_codec_uls[6+long_gop];
1919 1920 1921 1922
    }
    return NULL;
}

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

1981 1982
static uint64_t mxf_parse_timestamp(time_t timestamp)
{
1983 1984
    struct tm tmbuf;
    struct tm *time = gmtime_r(&timestamp, &tmbuf);
1985 1986
    if (!time)
        return 0;
1987 1988 1989 1990 1991 1992 1993 1994
    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;
}

1995 1996 1997
static void mxf_gen_umid(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
1998
    uint32_t seed = av_get_random_seed();
1999 2000 2001 2002 2003
    uint64_t umid = seed + 0x5294713400000000LL;

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

2004
    mxf->instance_number = seed & 0xFFFFFF;
2005 2006
}

2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
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);
}

2020
static int mxf_write_header(AVFormatContext *s)
2021 2022
{
    MXFContext *mxf = s->priv_data;
2023
    int i, ret;
2024
    uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
2025
    const MXFSamplesPerFrame *spf = NULL;
2026 2027
    AVDictionaryEntry *t;
    int64_t timestamp = 0;
2028

2029 2030 2031
    if (!s->nb_streams)
        return -1;

2032 2033 2034 2035 2036
    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;
    }

2037 2038
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
2039
        MXFStreamContext *sc = av_mallocz(sizeof(*sc));
2040 2041 2042
        if (!sc)
            return AVERROR(ENOMEM);
        st->priv_data = sc;
2043

2044
        if (((i == 0) ^ (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)) && s->oformat != &ff_mxf_opatom_muxer) {
2045 2046 2047 2048
            av_log(s, AV_LOG_ERROR, "there must be exactly one video stream and it must be the first one\n");
            return -1;
        }

2049
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2050
            const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(st->codec->pix_fmt);
2051
            // TODO: should be avg_frame_rate
2052
            AVRational rate, tbc = st->time_base;
2053 2054
            // Default component depth to 8
            sc->component_depth = 8;
2055
            sc->h_chroma_sub_sample = 2;
2056
            sc->color_siting = 0xFF;
2057 2058

            if (pix_desc) {
2059 2060
                sc->component_depth     = pix_desc->comp[0].depth_minus1 + 1;
                sc->h_chroma_sub_sample = 1 << pix_desc->log2_chroma_w;
2061
            }
2062 2063 2064 2065 2066 2067
            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;
            }
2068

2069
            mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num;
2070
            spf = ff_mxf_get_samples_per_frame(s, tbc);
2071
            if (!spf) {
2072 2073 2074
                av_log(s, AV_LOG_ERROR, "Unsupported video frame rate %d/%d\n",
                       tbc.den, tbc.num);
                return AVERROR(EINVAL);
2075
            }
2076
            mxf->time_base = spf->time_base;
2077
            rate = av_inv_q(mxf->time_base);
2078
            avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
2079
            if((ret = mxf_init_timecode(s, st, rate)) < 0)
2080
                return ret;
2081

2082
            sc->video_bit_rate = st->codec->bit_rate ? st->codec->bit_rate : st->codec->rc_max_rate;
2083
            if (s->oformat == &ff_mxf_d10_muxer) {
2084 2085 2086 2087
                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;
2088
                } else if (sc->video_bit_rate == 40000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2089 2090
                    if (mxf->time_base.den == 25) sc->index = 7;
                    else                          sc->index = 9;
2091
                } else if (sc->video_bit_rate == 30000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2092 2093
                    if (mxf->time_base.den == 25) sc->index = 11;
                    else                          sc->index = 13;
2094
                } else {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2095 2096 2097 2098 2099
                    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
2100
                mxf->edit_unit_byte_count += 16 + 4 + (uint64_t)sc->video_bit_rate *
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2101 2102
                    mxf->time_base.num / (8*mxf->time_base.den);
                mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
2103
                mxf->edit_unit_byte_count += 16 + 4 + 4 + spf->samples_per_frame[0]*8*4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2104
                mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
2105 2106

                sc->signal_standard = 1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2107
            }
2108 2109
            if (mxf->signal_standard >= 0)
                sc->signal_standard = mxf->signal_standard;
2110
        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
2111 2112 2113 2114
            if (st->codec->sample_rate != 48000) {
                av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
                return -1;
            }
2115
            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
2116
            if (s->oformat == &ff_mxf_d10_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2117 2118 2119 2120
                if (st->index != 1) {
                    av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n");
                    return -1;
                }
2121 2122
                if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE &&
                    st->codec->codec_id != AV_CODEC_ID_PCM_S24LE) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2123 2124 2125
                    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;
2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
            } else if (s->oformat == &ff_mxf_opatom_muxer) {
                AVRational tbc = av_inv_q(mxf->audio_edit_rate);

                if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE &&
                    st->codec->codec_id != AV_CODEC_ID_PCM_S24LE) {
                    av_log(s, AV_LOG_ERROR, "Only pcm_s16le and pcm_s24le audio codecs are implemented\n");
                    return AVERROR_PATCHWELCOME;
                }
                if (st->codec->channels != 1) {
                    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;
                mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
                sc->index = 2;
            } else {
                mxf->slice_count = 1;
            }
2155
        }
2156

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2157
        if (!sc->index) {
2158 2159 2160 2161 2162 2163
            sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id);
            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
2164
        }
2165

2166
        sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
2167

2168 2169
        memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15);
        sc->track_essence_element_key[15] = present[sc->index];
2170
        PRINT_KEY(s, "track essence element key", sc->track_essence_element_key);
2171 2172 2173 2174

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

2177
    if (s->oformat == &ff_mxf_d10_muxer || s->oformat == &ff_mxf_opatom_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2178 2179 2180
        mxf->essence_container_count = 1;
    }

2181
    if (!(s->flags & AVFMT_FLAG_BITEXACT))
2182 2183
        mxf_gen_umid(s);

2184 2185 2186 2187
    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];
2188 2189 2190 2191
        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);
2192 2193
    }

2194 2195
    if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
        timestamp = ff_iso8601_to_unix_time(t->value);
2196 2197
    if (timestamp)
        mxf->timestamp = mxf_parse_timestamp(timestamp);
2198 2199 2200 2201 2202 2203 2204 2205
    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);
2206
    mxf->timecode_track->index = -1;
2207

2208
    if (!spf)
2209
        spf = ff_mxf_get_samples_per_frame(s, (AVRational){ 1, 25 });
2210

2211
    if (ff_audio_interleave_init(s, spf->samples_per_frame, mxf->time_base) < 0)
2212 2213
        return -1;

2214 2215 2216
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2217 2218 2219 2220 2221 2222
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;
2223
    AVIOContext *pb = s->pb;
2224
    unsigned frame;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2225 2226
    uint32_t time_code;

2227
    frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2228 2229

    // write system metadata pack
2230
    avio_write(pb, system_metadata_pack_key, 16);
2231
    klv_encode_ber4_length(pb, 57);
2232 2233 2234 2235
    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
2236
    avio_wb16(pb, (mxf->tc.start + frame) & 0xFFFF); // continuity count, supposed to overflow
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2237
    if (mxf->essence_container_count > 1)
2238
        avio_write(pb, multiple_desc_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2239 2240
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
2241
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2242
    }
2243 2244 2245
    avio_w8(pb, 0);
    avio_wb64(pb, 0);
    avio_wb64(pb, 0); // creation date/time stamp
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2246

2247
    avio_w8(pb, 0x81); // SMPTE 12M time code
2248
    time_code = av_timecode_get_smpte_from_framenum(&mxf->tc, frame);
2249 2250 2251
    avio_wb32(pb, time_code);
    avio_wb32(pb, 0); // binary group data
    avio_wb64(pb, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2252 2253

    // write system metadata package set
2254
    avio_write(pb, system_metadata_package_set_key, 16);
2255
    klv_encode_ber4_length(pb, 35);
2256 2257
    avio_w8(pb, 0x83); // UMID
    avio_wb16(pb, 0x20);
2258
    mxf_write_umid(s, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2259 2260
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2261 2262 2263
static void mxf_write_d10_video_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
2264
    AVIOContext *pb = s->pb;
2265 2266
    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
2267 2268 2269 2270 2271 2272 2273
        (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);
2274
    avio_write(pb, pkt->data, pkt->size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2275 2276 2277 2278

    // ensure CBR muxing by padding to correct video frame size
    pad = packet_size - pkt->size - 16 - 4;
    if (pad > 20) {
2279
        avio_write(s->pb, klv_fill_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2280 2281
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
2282
        ffio_fill(s->pb, 0, pad);
2283
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2284 2285
    } else {
        av_log(s, AV_LOG_WARNING, "cannot fill d-10 video packet\n");
Paul B Mahol's avatar
Paul B Mahol committed
2286
        ffio_fill(s->pb, 0, pad);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2287 2288 2289 2290 2291 2292
    }
}

static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
2293
    AVIOContext *pb = s->pb;
2294
    int frame_size = pkt->size / st->codec->block_align;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2295 2296 2297 2298 2299 2300
    uint8_t *samples = pkt->data;
    uint8_t *end = pkt->data + pkt->size;
    int i;

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

2301 2302 2303
    avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1));
    avio_wl16(pb, frame_size);
    avio_w8(pb, (1<<st->codec->channels)-1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2304 2305 2306 2307

    while (samples < end) {
        for (i = 0; i < st->codec->channels; i++) {
            uint32_t sample;
2308
            if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE) {
2309
                sample = AV_RL24(samples)<< 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2310 2311
                samples += 3;
            } else {
2312
                sample = AV_RL16(samples)<<12;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2313 2314
                samples += 2;
            }
2315
            avio_wl32(pb, sample | i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2316 2317
        }
        for (; i < 8; i++)
2318
            avio_wl32(pb, i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2319 2320 2321
    }
}

2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 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
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;
}

2373
static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
2374
{
2375
    MXFContext *mxf = s->priv_data;
2376
    AVIOContext *pb = s->pb;
2377 2378
    AVStream *st = s->streams[pkt->stream_index];
    MXFStreamContext *sc = st->priv_data;
2379
    MXFIndexEntry ie = {0};
2380
    int err;
2381

2382
    if (!mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) {
2383 2384 2385
        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;
2386
            av_log(s, AV_LOG_ERROR, "could not allocate index entries\n");
2387
            return err;
2388 2389 2390
        }
    }

2391
    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
2392
        if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
2393 2394
            av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
            return -1;
2395
        }
2396
    } else if (st->codec->codec_id == AV_CODEC_ID_DNXHD) {
2397 2398 2399 2400
        if (!mxf_parse_dnxhd_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
            return -1;
        }
2401
    } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) {
2402 2403 2404 2405
        if (!mxf_parse_dv_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
            return -1;
        }
2406 2407 2408 2409 2410
    } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
        if (!mxf_parse_h264_frame(s, st, pkt, &ie)) {
            av_log(s, AV_LOG_ERROR, "could not get h264 profile\n");
            return -1;
        }
2411 2412
    }

2413 2414 2415
    if (s->oformat == &ff_mxf_opatom_muxer)
        return mxf_write_opatom_packet(s, pkt, &ie);

2416
    if (!mxf->header_written) {
2417
        if (mxf->edit_unit_byte_count) {
2418 2419
            if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0)
                return err;
2420 2421 2422
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        } else {
2423 2424
            if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0)
                return err;
2425
        }
2426 2427 2428
        mxf->header_written = 1;
    }

2429
    if (st->index == 0) {
2430 2431
        if (!mxf->edit_unit_byte_count &&
            (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) &&
2432
            !(ie.flags & 0x33)) { // I frame, Gop start
2433
            mxf_write_klv_fill(s);
2434 2435
            if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0)
                return err;
2436 2437 2438 2439
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2440
        mxf_write_klv_fill(s);
2441
        mxf_write_system_item(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2442

2443 2444
        if (!mxf->edit_unit_byte_count) {
            mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
2445 2446
            mxf->index_entries[mxf->edit_units_count].flags = ie.flags;
            mxf->index_entries[mxf->edit_units_count].temporal_ref = ie.temporal_ref;
2447 2448
            mxf->body_offset += KAG_SIZE; // size of system element
        }
2449
        mxf->edit_units_count++;
2450
    } else if (!mxf->edit_unit_byte_count && st->index == 1) {
2451 2452
        mxf->index_entries[mxf->edit_units_count-1].slice_offset =
            mxf->body_offset - mxf->index_entries[mxf->edit_units_count-1].offset;
2453 2454
    }

2455
    mxf_write_klv_fill(s);
2456
    avio_write(pb, sc->track_essence_element_key, 16); // write key
2457
    if (s->oformat == &ff_mxf_d10_muxer) {
2458
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
2459 2460 2461 2462 2463
            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
2464
        avio_write(pb, pkt->data, pkt->size);
2465 2466
        mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size);
    }
2467

2468
    avio_flush(pb);
2469

2470 2471 2472
    return 0;
}

2473 2474 2475
static void mxf_write_random_index_pack(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2476
    AVIOContext *pb = s->pb;
2477
    uint64_t pos = avio_tell(pb);
2478
    int i;
2479

2480
    avio_write(pb, random_index_pack_key, 16);
2481
    klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count);
2482

2483
    if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer)
2484
        avio_wb32(pb, 1); // BodySID of header partition
2485
    else
2486 2487
        avio_wb32(pb, 0);
    avio_wb64(pb, 0); // offset of header partition
2488

2489
    for (i = 0; i < mxf->body_partitions_count; i++) {
2490 2491
        avio_wb32(pb, 1); // BodySID
        avio_wb64(pb, mxf->body_partition_offset[i]);
2492 2493
    }

2494 2495
    avio_wb32(pb, 0); // BodySID of footer partition
    avio_wb64(pb, mxf->footer_partition_offset);
2496

2497
    avio_wb32(pb, avio_tell(pb) - pos + 4);
2498 2499
}

2500
static int mxf_write_footer(AVFormatContext *s)
2501
{
2502
    MXFContext *mxf = s->priv_data;
2503
    AVIOContext *pb = s->pb;
2504
    int err = 0;
2505

2506 2507 2508 2509 2510 2511 2512
    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;
    }

2513 2514
    mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;

2515
    mxf_write_klv_fill(s);
2516
    mxf->footer_partition_offset = avio_tell(pb);
2517
    if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { // no need to repeat index
2518
        if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0)
2519
            goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2520
    } else {
2521
        if ((err = mxf_write_partition(s, 0, 2, footer_partition_key, 0)) < 0)
2522
            goto end;
2523 2524
        mxf_write_klv_fill(s);
        mxf_write_index_table_segment(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2525
    }
2526

2527
    mxf_write_klv_fill(s);
2528 2529
    mxf_write_random_index_pack(s);

2530
    if (s->pb->seekable) {
2531 2532 2533 2534
        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)
2535
                goto end;
2536 2537
        }

2538
        avio_seek(pb, 0, SEEK_SET);
2539
        if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) {
2540
            if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0)
2541
                goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2542 2543
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
2544
        } else {
2545
            if ((err = mxf_write_partition(s, 0, 0, header_closed_partition_key, 1)) < 0)
2546
                goto end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2547
        }
2548
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2549

2550
end:
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2551 2552
    ff_audio_interleave_close(s);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2553
    av_freep(&mxf->index_entries);
2554
    av_freep(&mxf->body_partition_offset);
2555 2556
    av_freep(&mxf->timecode_track->priv_data);
    av_freep(&mxf->timecode_track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2557

2558
    mxf_free(s);
2559

2560
    return err < 0 ? err : 0;
2561
}
2562

2563
static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
2564
{
2565 2566 2567 2568
    int i, stream_count = 0;

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

    if (stream_count && (s->nb_streams == stream_count || flush)) {
2571
        AVPacketList *pktl = s->internal->packet_buffer;
2572
        if (s->nb_streams != stream_count) {
2573
            AVPacketList *last = NULL;
2574
            // find last packet in edit unit
2575
            while (pktl) {
2576
                if (!stream_count || pktl->pkt.stream_index == 0)
2577
                    break;
2578
                last = pktl;
2579
                pktl = pktl->next;
2580
                stream_count--;
2581
            }
2582 2583 2584
            // purge packet queue
            while (pktl) {
                AVPacketList *next = pktl->next;
2585 2586 2587

                if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
                    s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
2588 2589 2590 2591
                av_free_packet(&pktl->pkt);
                av_freep(&pktl);
                pktl = next;
            }
2592 2593 2594
            if (last)
                last->next = NULL;
            else {
2595 2596
                s->internal->packet_buffer = NULL;
                s->internal->packet_buffer_end= NULL;
2597
                goto out;
2598
            }
2599
            pktl = s->internal->packet_buffer;
2600 2601
        }

2602
        *out = pktl->pkt;
2603
        av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts);
2604
        s->internal->packet_buffer = pktl->next;
2605 2606
        if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
            s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
2607 2608
        if(!s->internal->packet_buffer)
            s->internal->packet_buffer_end= NULL;
2609
        av_freep(&pktl);
2610 2611
        return 1;
    } else {
2612
    out:
2613 2614 2615 2616 2617 2618 2619
        av_init_packet(out);
        return 0;
    }
}

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

2623 2624
    return next->dts > pkt->dts ||
        (next->dts == pkt->dts && sc->order < sc2->order);
2625 2626 2627 2628
}

static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
{
2629
    return ff_audio_rechunk_interleave(s, out, pkt, flush,
2630
                               mxf_interleave_get_packet, mxf_compare_timestamps);
2631 2632
}

2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652
#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"},



2653
static const AVOption mxf_options[] = {
2654
    MXF_COMMON_OPTIONS
2655 2656 2657 2658 2659 2660 2661 2662 2663 2664
    { NULL },
};

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

2665
static const AVOption d10_options[] = {
2666
    { "d10_channelcount", "Force/set channelcount in generic sound essence descriptor",
2667
      offsetof(MXFContext, channel_count), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 8, AV_OPT_FLAG_ENCODING_PARAM},
2668
    MXF_COMMON_OPTIONS
2669 2670 2671 2672 2673 2674 2675 2676 2677 2678
    { 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,
};

2679 2680 2681
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 },
2682
    MXF_COMMON_OPTIONS
2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
    { 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,
};

2693
AVOutputFormat ff_mxf_muxer = {
2694
    .name              = "mxf",
2695
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
2696 2697 2698
    .mime_type         = "application/mxf",
    .extensions        = "mxf",
    .priv_data_size    = sizeof(MXFContext),
2699 2700
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2701 2702 2703 2704 2705
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
2706
    .priv_class        = &mxf_muxer_class,
2707
};
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2708

2709
AVOutputFormat ff_mxf_d10_muxer = {
2710
    .name              = "mxf_d10",
2711
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"),
2712 2713
    .mime_type         = "application/mxf",
    .priv_data_size    = sizeof(MXFContext),
2714 2715
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2716 2717 2718 2719 2720
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
2721
    .priv_class        = &mxf_d10_muxer_class,
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2722
};
2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736

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