mxfenc.c 83.9 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 29 30 31 32
 *
 * 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
 * SMPTE RP210: SMPTE Metadata Dictionary
 * SMPTE RP224: Registry of SMPTE Universal Labels
 */

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

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

50
extern AVOutputFormat ff_mxf_d10_muxer;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
51

52
#define EDIT_UNITS_PER_BODY 250
53
#define KAG_SIZE 512
54

55 56 57 58 59
typedef struct {
    int local_tag;
    UID uid;
} MXFLocalTagPair;

60 61 62
typedef struct {
    uint8_t flags;
    uint64_t offset;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
63
    unsigned slice_offset; ///< offset of audio slice
64
    uint16_t temporal_ref;
65 66
} MXFIndexEntry;

67
typedef struct {
68
    AudioInterleaveContext aic;
69
    UID track_essence_element_key;
70
    int index;               ///< index in mxf_essence_container_uls table
71
    const UID *codec_ul;
72
    int order;               ///< interleaving order if dts are equal
73
    int interlaced;          ///< whether picture is interlaced
74
    int field_dominance;     ///< tff=1, bff=2
75
    int component_depth;
76
    int temporal_reordering;
77
    AVRational aspect_ratio; ///< display aspect ratio
78
    int closed_gop;          ///< gop is closed, used in mpeg-2 frame parsing
79
    int video_bit_rate;
80 81
} MXFStreamContext;

82 83 84
typedef struct {
    UID container_ul;
    UID element_ul;
85
    UID codec_ul;
86
    void (*write_desc)(AVFormatContext *, AVStream *);
87
} MXFContainerEssenceEntry;
88

89
static const struct {
90
    enum AVCodecID id;
91 92
    int index;
} mxf_essence_mappings[] = {
93 94 95
    { AV_CODEC_ID_MPEG2VIDEO, 0 },
    { AV_CODEC_ID_PCM_S24LE,  1 },
    { AV_CODEC_ID_PCM_S16LE,  1 },
96 97
    { AV_CODEC_ID_DVVIDEO,   15 },
    { AV_CODEC_ID_DNXHD,     24 },
98
    { AV_CODEC_ID_NONE }
99 100
};

101
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st);
102
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st);
103
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
104 105
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
106

107
static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
108
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 },
109
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
110
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
111
      mxf_write_mpegvideo_desc },
112 113 114
    { { 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 },
115
      mxf_write_aes3_desc },
116
    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 },
117
      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x16,0x01,0x01,0x00 },
118
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
119
      mxf_write_wav_desc },
Baptiste Coudurier's avatar
Baptiste Coudurier committed
120 121 122 123 124 125 126 127 128 129 130 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
    // 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 },
174
    // DV Unknown
175 176 177 178 179 180 181 182 183 184 185 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
    { { 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 },
219 220 221
    // 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 },
222
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 },
223 224 225 226
      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 },
227
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 },
228 229 230 231
      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 },
232
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 },
233 234 235 236
      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 },
237
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 },
238 239 240 241
      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 },
242
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 },
243 244 245 246
      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 },
247
      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 },
248 249 250 251
      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 },
252
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 },
253 254 255 256
      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 },
257
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 },
258 259 260 261
      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 },
262
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 },
263 264 265 266
      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 },
267
      { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 },
268
      mxf_write_cdci_desc },
269
    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
270
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
271
      { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
272
      NULL },
273 274
};

275
typedef struct MXFContext {
276
    AVClass *av_class;
277
    int64_t footer_partition_offset;
278
    int essence_container_count;
279
    AVRational time_base;
280
    int header_written;
281 282
    MXFIndexEntry *index_entries;
    unsigned edit_units_count;
283
    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
284
    uint8_t slice_count;  ///< index slice count minus 1 (1 if no audio, 0 otherwise)
285 286 287 288
    int last_indexed_edit_unit;
    uint64_t *body_partition_offset;
    unsigned body_partitions_count;
    int last_key_index;  ///< index of last key frame
289
    uint64_t duration;
290
    AVTimecode tc;       ///< timecode context
291 292
    AVStream *timecode_track;
    int timecode_base;       ///< rounded time code base (25 or 30)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
293
    int edit_unit_byte_count; ///< fixed edit unit byte count
294
    uint64_t body_offset;
295 296
    uint32_t instance_number;
    uint8_t umid[16];        ///< unique material identifier
297
} MXFContext;
298

299
static const uint8_t uuid_base[]            = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
300
static const uint8_t umid_ul[]              = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 };
301 302 303 304

/**
 * complete key for operation pattern, partitions, and primer pack
 */
305
static const uint8_t op1a_ul[]                     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x01,0x09,0x00 };
306 307 308 309
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 };
310 311
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
312
static const uint8_t klv_fill_key[]                = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 };
313
static const uint8_t body_partition_key[]          = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }; // ClosedComplete
314

315 316 317 318
/**
 * 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 };
319
static const uint8_t multiple_desc_ul[]     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x0D,0x01,0x03,0x01,0x02,0x7F,0x01,0x00 };
320

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
/**
 * 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 */
338
    { 0x3C04, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x05,0x01,0x00,0x00}}, /* Version String */
339 340 341 342
    { 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 */
343
    { 0x1902, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x05,0x02,0x00,0x00}}, /* Package strong reference batch */
344 345 346 347 348 349 350 351 352 353 354
    // 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 */
    { 0x4403, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x05,0x00,0x00}}, /* Tracks Strong reference array */
    { 0x4701, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x03,0x00,0x00}}, /* Descriptor */
    // Track
    { 0x4801, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x01,0x07,0x01,0x01,0x00,0x00,0x00,0x00}}, /* Track ID */
355
    { 0x4804, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x01,0x04,0x01,0x03,0x00,0x00,0x00,0x00}}, /* Track Number */
356 357 358 359 360 361 362 363
    { 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
364
    { 0x1201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x04,0x00,0x00}}, /* Start position */
365 366
    { 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 */
367 368 369 370
    // 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 */
371 372
    // File Descriptor
    { 0x3F01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x04,0x06,0x0B,0x00,0x00}}, /* Sub Descriptors reference array */
373 374
    { 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 */
375 376
    { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* Essence Container */
    // Generic Picture Essence Descriptor
377
    { 0x320C, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Frame Layout */
378
    { 0x320D, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x02,0x05,0x00,0x00,0x00}}, /* Video Line Map */
379 380
    { 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 */
381 382
    { 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 */
383 384
    { 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 */
385
    { 0x3212, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x01,0x06,0x00,0x00,0x00}}, /* Field Dominance (Opt) */
386 387 388
    // 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 */
389
    // Generic Sound Essence Descriptor
390
    { 0x3D02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Locked/Unlocked */
391 392 393
    { 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 */
394
    { 0x3D06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x02,0x04,0x02,0x00,0x00,0x00,0x00}}, /* Sound Essence Compression */
395 396 397 398
    // 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 */
399
    { 0x3F05, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x06,0x02,0x01,0x00,0x00,0x00,0x00}}, /* Edit Unit Byte Count */
400 401 402 403
    { 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
404 405
    // MPEG video Descriptor
    { 0x8000, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0B,0x00,0x00}}, /* BitRate */
406
    { 0x8007, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0A,0x00,0x00}}, /* ProfileAndLevel */
407 408 409
    // 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 */
410 411
};

412
static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value)
413
{
414 415 416
    avio_write(pb, uuid_base, 12);
    avio_wb16(pb, type);
    avio_wb16(pb, value);
417 418
}

419
static void mxf_write_umid(AVFormatContext *s, int type)
420
{
421
    MXFContext *mxf = s->priv_data;
422 423 424 425
    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);
426
}
427

428
static void mxf_write_refs_count(AVIOContext *pb, int ref_count)
429
{
430 431
    avio_wb32(pb, ref_count);
    avio_wb32(pb, 16);
432 433
}

434 435 436 437 438 439 440 441
static int klv_ber_length(uint64_t len)
{
    if (len < 128)
        return 1;
    else
        return (av_log2(len) >> 3) + 2;
}

442
static int klv_encode_ber_length(AVIOContext *pb, uint64_t len)
443 444 445 446 447
{
    // Determine the best BER size
    int size;
    if (len < 128) {
        //short form
448
        avio_w8(pb, len);
449 450 451 452 453 454
        return 1;
    }

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

    // long form
455
    avio_w8(pb, 0x80 + size);
456
    while(size) {
457
        size--;
458
        avio_w8(pb, len >> 8 * size & 0xff);
459 460 461 462
    }
    return 0;
}

463
static void klv_encode_ber4_length(AVIOContext *pb, int len)
464
{
465 466
    avio_w8(pb, 0x80 + 3);
    avio_wb24(pb, len);
467 468
}

469
/*
470
 * Get essence container ul index
471
 */
472
static int mxf_get_essence_container_ul_index(enum AVCodecID id)
473
{
474
    int i;
475 476 477
    for (i = 0; mxf_essence_mappings[i].id; i++)
        if (mxf_essence_mappings[i].id == id)
            return mxf_essence_mappings[i].index;
478
    return -1;
479 480
}

481
static void mxf_write_primer_pack(AVFormatContext *s)
482
{
483
    AVIOContext *pb = s->pb;
484 485
    int local_tag_number, i = 0;

486
    local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch);
487

488
    avio_write(pb, primer_pack_key, 16);
489 490
    klv_encode_ber_length(pb, local_tag_number * 18 + 8);

491 492
    avio_wb32(pb, local_tag_number); // local_tag num
    avio_wb32(pb, 18); // item size, always 18 according to the specs
493 494

    for (i = 0; i < local_tag_number; i++) {
495 496
        avio_wb16(pb, mxf_local_tag_batch[i].local_tag);
        avio_write(pb, mxf_local_tag_batch[i].uid, 16);
497 498 499
    }
}

500
static void mxf_write_local_tag(AVIOContext *pb, int size, int tag)
501
{
502 503
    avio_wb16(pb, tag);
    avio_wb16(pb, size);
504 505
}

506
static void mxf_write_metadata_key(AVIOContext *pb, unsigned int value)
507
{
508 509
    avio_write(pb, header_metadata_key, 13);
    avio_wb24(pb, value);
510 511
}

512 513 514 515 516
static void mxf_free(AVFormatContext *s)
{
    int i;

    for (i = 0; i < s->nb_streams; i++) {
517
        AVStream *st = s->streams[i];
518 519 520 521
        av_freep(&st->priv_data);
    }
}

522
static const MXFCodecUL *mxf_get_data_definition_ul(int type)
523
{
524 525 526
    const MXFCodecUL *uls = ff_mxf_data_definition_uls;
    while (uls->uid[0]) {
        if (type == uls->id)
527
            break;
528
        uls++;
529 530 531 532
    }
    return uls;
}

533 534 535 536
//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)

537
static void mxf_write_essence_container_refs(AVFormatContext *s)
538
{
539
    MXFContext *c = s->priv_data;
540
    AVIOContext *pb = s->pb;
541
    int i;
542

543
    mxf_write_refs_count(pb, DESCRIPTOR_COUNT(c->essence_container_count));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
544 545
    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
546
        MXFStreamContext *sc = s->streams[i]->priv_data;
547
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
548
    }
549 550 551

    if (c->essence_container_count > 1)
        avio_write(pb, multiple_desc_ul, 16);
552 553
}

554 555 556
static void mxf_write_preface(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
557
    AVIOContext *pb = s->pb;
558 559 560

    mxf_write_metadata_key(pb, 0x012f00);
    PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
561
    klv_encode_ber_length(pb, 130 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
562 563 564 565 566 567

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

568
    // last modified date
569
    mxf_write_local_tag(pb, 8, 0x3B02);
570
    avio_wb64(pb, mxf->timestamp);
571 572 573

    // write version
    mxf_write_local_tag(pb, 2, 0x3B05);
574
    avio_wb16(pb, 258); // v1.2
575 576 577 578 579 580 581 582 583 584

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

585
    // operational pattern
586
    mxf_write_local_tag(pb, 16, 0x3B09);
587
    avio_write(pb, op1a_ul, 16);
588 589

    // write essence_container_refs
590
    mxf_write_local_tag(pb, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A);
591
    mxf_write_essence_container_refs(s);
592 593 594

    // write dm_scheme_refs
    mxf_write_local_tag(pb, 8, 0x3B0B);
595
    avio_wb64(pb, 0);
596 597
}

598
/*
599
 * Write a local tag containing an ascii string as utf-16
600
 */
601
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
602
{
603
    int i, size = strlen(value);
604
    mxf_write_local_tag(pb, size*2, tag);
605
    for (i = 0; i < size; i++)
606
        avio_wb16(pb, value[i]);
607 608
}

609 610
static void mxf_write_identification(AVFormatContext *s)
{
611
    MXFContext *mxf = s->priv_data;
612
    AVIOContext *pb = s->pb;
613
    const char *company = "FFmpeg";
614
    const char *product = "OP1a Muxer";
615
    const char *version;
616
    int length;
617 618 619 620

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
621
    version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ?
622
        "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
623
    length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16
624 625 626 627 628 629
    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
630

631 632 633 634
    // write generation uid
    mxf_write_local_tag(pb, 16, 0x3C09);
    mxf_write_uuid(pb, Identification, 1);

635 636
    mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
    mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
637
    mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
638 639 640 641 642

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

643
    // modification date
644
    mxf_write_local_tag(pb, 8, 0x3C06);
645
    avio_wb64(pb, mxf->timestamp);
646 647 648 649
}

static void mxf_write_content_storage(AVFormatContext *s)
{
650
    AVIOContext *pb = s->pb;
651 652 653

    mxf_write_metadata_key(pb, 0x011800);
    PRINT_KEY(s, "content storage key", pb->buf_ptr - 16);
654
    klv_encode_ber_length(pb, 92);
655 656 657 658 659

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

661 662 663 664 665
    // 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);
666 667 668 669 670

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

673
static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
674
{
675
    MXFContext *mxf = s->priv_data;
676
    AVIOContext *pb = s->pb;
677
    MXFStreamContext *sc = st->priv_data;
678 679 680 681 682 683 684

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

688 689
    // write track id
    mxf_write_local_tag(pb, 4, 0x4801);
690
    avio_wb32(pb, st->index+2);
691

692
    // write track number
693
    mxf_write_local_tag(pb, 4, 0x4804);
694
    if (type == MaterialPackage)
695
        avio_wb32(pb, 0); // track number of material package is 0
696
    else
697
        avio_write(pb, sc->track_essence_element_key + 12, 4);
698 699

    mxf_write_local_tag(pb, 8, 0x4B01);
700 701
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
702 703 704

    // write origin
    mxf_write_local_tag(pb, 8, 0x4B02);
705
    avio_wb64(pb, 0);
706 707 708

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

712 713 714
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)
715
{
716
    MXFContext *mxf = s->priv_data;
717
    AVIOContext *pb = s->pb;
718

719 720
    // find data define uls
    mxf_write_local_tag(pb, 16, 0x0201);
721
    if (st == mxf->timecode_track)
722
        avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
723 724
    else {
        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
725
        avio_write(pb, data_def_ul->uid, 16);
726
    }
727 728 729

    // write duration
    mxf_write_local_tag(pb, 8, 0x0202);
730
    avio_wb64(pb, mxf->duration);
731 732
}

733
static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
734
{
735
    MXFContext *mxf = s->priv_data;
736
    AVIOContext *pb = s->pb;
737
    enum MXFMetadataSetType component;
738 739 740 741 742 743

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

    PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
747
    mxf_write_common_fields(s, st);
748 749 750 751

    // write structural component
    mxf_write_local_tag(pb, 16 + 8, 0x1001);
    mxf_write_refs_count(pb, 1);
752 753 754
    if (st == mxf->timecode_track)
        component = TimecodeComponent;
    else
755 756 757
        component = SourceClip;
    if (type == SourcePackage)
        component += TypeBottom;
758 759 760
    mxf_write_uuid(pb, component, st->index);
}

761
static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
762 763
{
    MXFContext *mxf = s->priv_data;
764
    AVIOContext *pb = s->pb;
765 766 767 768 769 770

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

    // UID
    mxf_write_local_tag(pb, 16, 0x3C0A);
771 772
    mxf_write_uuid(pb, type == MaterialPackage ? TimecodeComponent :
                   TimecodeComponent + TypeBottom, st->index);
773 774 775 776 777

    mxf_write_common_fields(s, st);

    // Start Time Code
    mxf_write_local_tag(pb, 8, 0x1501);
778
    avio_wb64(pb, mxf->tc.start);
779 780 781

    // Rounded Time Code Base
    mxf_write_local_tag(pb, 2, 0x1502);
782
    avio_wb16(pb, mxf->timecode_base);
783 784 785

    // Drop Frame
    mxf_write_local_tag(pb, 1, 0x1503);
786
    avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
787 788
}

789
static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
790
{
791
    AVIOContext *pb = s->pb;
792 793 794 795 796 797 798 799
    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);
800
    mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index);
801 802

    PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
803
    mxf_write_common_fields(s, st);
804 805 806

    // write start_position
    mxf_write_local_tag(pb, 8, 0x1201);
807
    avio_wb64(pb, 0);
808

809
    // write source package uid, end of the reference
810 811
    mxf_write_local_tag(pb, 32, 0x1101);
    if (type == SourcePackage) {
812
        for (i = 0; i < 4; i++)
813
            avio_wb64(pb, 0);
814
    } else
815
        mxf_write_umid(s, 1);
816

817
    // write source track id
818 819
    mxf_write_local_tag(pb, 4, 0x1102);
    if (type == SourcePackage)
820
        avio_wb32(pb, 0);
821
    else
822
        avio_wb32(pb, st->index+2);
823 824
}

825 826
static void mxf_write_multi_descriptor(AVFormatContext *s)
{
827
    MXFContext *mxf = s->priv_data;
828
    AVIOContext *pb = s->pb;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
829
    const uint8_t *ul;
830 831 832 833
    int i;

    mxf_write_metadata_key(pb, 0x014400);
    PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16);
834
    klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams);
835 836 837 838 839 840 841

    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);
842 843
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
844 845 846

    // write essence container ul
    mxf_write_local_tag(pb, 16, 0x3004);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
847 848
    if (mxf->essence_container_count > 1)
        ul = multiple_desc_ul;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
849 850 851 852
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
        ul = mxf_essence_container_uls[sc->index].container_ul;
    }
853
    avio_write(pb, ul, 16);
854 855 856 857

    // write sub descriptor refs
    mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01);
    mxf_write_refs_count(pb, s->nb_streams);
858
    for (i = 0; i < s->nb_streams; i++)
859 860 861
        mxf_write_uuid(pb, SubDescriptor, i);
}

862
static void mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
863
{
864
    MXFContext *mxf = s->priv_data;
865
    MXFStreamContext *sc = st->priv_data;
866
    AVIOContext *pb = s->pb;
867

868
    avio_write(pb, key, 16);
869
    klv_encode_ber4_length(pb, size+20+8+12+20);
870 871 872 873 874

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

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

877
    mxf_write_local_tag(pb, 8, 0x3001);
878 879
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
880

881
    mxf_write_local_tag(pb, 16, 0x3004);
882
    avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
883 884
}

885 886
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 };
887
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
888 889
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 };
890

891
static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
892
{
893
    MXFStreamContext *sc = st->priv_data;
894
    AVIOContext *pb = s->pb;
895
    int stored_height = (st->codec->height+15)/16*16;
896
    int display_height;
897
    int f1, f2;
898 899 900
    unsigned desc_size = size+8+8+8+8+8+8+5+16+sc->interlaced*4+12+20;
    if (sc->interlaced && sc->field_dominance)
        desc_size += 5;
901

902
    mxf_write_generic_desc(s, st, key, desc_size);
903 904

    mxf_write_local_tag(pb, 4, 0x3203);
905
    avio_wb32(pb, st->codec->width);
906 907

    mxf_write_local_tag(pb, 4, 0x3202);
908
    avio_wb32(pb, stored_height>>sc->interlaced);
909

910
    mxf_write_local_tag(pb, 4, 0x3209);
911
    avio_wb32(pb, st->codec->width);
912

913 914 915 916 917 918 919
    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;

920
    mxf_write_local_tag(pb, 4, 0x3208);
921
    avio_wb32(pb, display_height>>sc->interlaced);
922

923 924
    // component depth
    mxf_write_local_tag(pb, 4, 0x3301);
925
    avio_wb32(pb, sc->component_depth);
926 927 928

    // horizontal subsampling
    mxf_write_local_tag(pb, 4, 0x3302);
929
    avio_wb32(pb, 2);
930

931 932
    // frame layout
    mxf_write_local_tag(pb, 1, 0x320C);
933
    avio_w8(pb, sc->interlaced);
934

935 936
    // video line map
    switch (st->codec->height) {
937
    case  576: f1 = 23; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
938
    case  608: f1 =  7; f2 = 320; break;
939
    case  480: f1 = 20; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
940 941 942 943 944 945 946 947 948 949 950
    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;
    }

951
    mxf_write_local_tag(pb, 12+sc->interlaced*4, 0x320D);
952 953 954
    avio_wb32(pb, sc->interlaced ? 2 : 1);
    avio_wb32(pb, 4);
    avio_wb32(pb, f1);
955
    if (sc->interlaced)
956
        avio_wb32(pb, f2);
957

958
    mxf_write_local_tag(pb, 8, 0x320E);
959 960
    avio_wb32(pb, sc->aspect_ratio.num);
    avio_wb32(pb, sc->aspect_ratio.den);
961 962

    mxf_write_local_tag(pb, 16, 0x3201);
963
    avio_write(pb, *sc->codec_ul, 16);
964 965 966 967 968 969

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

970 971
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
972 973
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
{
974
    mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
975 976
}

977 978
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
{
979
    AVIOContext *pb = s->pb;
980
    MXFStreamContext *sc = st->priv_data;
981
    int profile_and_level = (st->codec->profile<<4) | st->codec->level;
982

983
    mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5);
984 985 986

    // bit rate
    mxf_write_local_tag(pb, 4, 0x8000);
987
    avio_wb32(pb, sc->video_bit_rate);
988 989 990 991 992

    // profile and level
    mxf_write_local_tag(pb, 1, 0x8007);
    if (!st->codec->profile)
        profile_and_level |= 0x80; // escape bit
993
    avio_w8(pb, profile_and_level);
994 995 996
}

static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
997
{
998
    AVIOContext *pb = s->pb;
999

1000
    mxf_write_generic_desc(s, st, key, size+5+12+8+8);
1001

1002
    // audio locked
1003
    mxf_write_local_tag(pb, 1, 0x3D02);
1004
    avio_w8(pb, 1);
1005 1006 1007

    // write audio sampling rate
    mxf_write_local_tag(pb, 8, 0x3D03);
1008 1009
    avio_wb32(pb, st->codec->sample_rate);
    avio_wb32(pb, 1);
1010 1011

    mxf_write_local_tag(pb, 4, 0x3D07);
1012
    avio_wb32(pb, st->codec->channels);
1013 1014

    mxf_write_local_tag(pb, 4, 0x3D01);
1015
    avio_wb32(pb, av_get_bits_per_sample(st->codec->codec_id));
1016 1017
}

1018
static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1019
{
1020
    AVIOContext *pb = s->pb;
1021

1022
    mxf_write_generic_sound_common(s, st, key, size+6+8);
1023 1024

    mxf_write_local_tag(pb, 2, 0x3D0A);
1025
    avio_wb16(pb, st->codec->block_align);
1026 1027 1028

    // avg bytes per sec
    mxf_write_local_tag(pb, 4, 0x3D09);
1029
    avio_wb32(pb, st->codec->block_align*st->codec->sample_rate);
1030 1031
}

1032
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st)
1033
{
1034
    mxf_write_wav_common(s, st, mxf_wav_descriptor_key, 0);
1035
}
1036

1037 1038
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st)
{
1039
    mxf_write_wav_common(s, st, mxf_aes3_descriptor_key, 0);
1040 1041
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1042 1043
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st)
{
1044
    mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1045 1046
}

1047 1048
static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type)
{
1049
    MXFContext *mxf = s->priv_data;
1050
    AVIOContext *pb = s->pb;
1051
    int i, track_count = s->nb_streams+1;
1052 1053 1054 1055

    if (type == MaterialPackage) {
        mxf_write_metadata_key(pb, 0x013600);
        PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
1056
        klv_encode_ber_length(pb, 92 + 16*track_count);
1057 1058 1059
    } else {
        mxf_write_metadata_key(pb, 0x013700);
        PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
1060
        klv_encode_ber_length(pb, 112 + 16*track_count); // 20 bytes length for descriptor reference
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
    }

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

1074
    // package creation date
1075
    mxf_write_local_tag(pb, 8, 0x4405);
1076
    avio_wb64(pb, mxf->timestamp);
1077

1078
    // package modified date
1079
    mxf_write_local_tag(pb, 8, 0x4404);
1080
    avio_wb64(pb, mxf->timestamp);
1081 1082

    // write track refs
1083 1084
    mxf_write_local_tag(pb, track_count*16 + 8, 0x4403);
    mxf_write_refs_count(pb, track_count);
1085 1086
    mxf_write_uuid(pb, type == MaterialPackage ? Track :
                   Track + TypeBottom, -1); // timecode track
1087 1088 1089 1090 1091 1092
    for (i = 0; i < s->nb_streams; i++)
        mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, i);

    // write multiple descriptor reference
    if (type == SourcePackage) {
        mxf_write_local_tag(pb, 16, 0x4701);
1093 1094 1095 1096 1097
        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
1098
    }
1099

1100 1101 1102 1103 1104
    // 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);

1105
    for (i = 0; i < s->nb_streams; i++) {
1106 1107 1108 1109
        AVStream *st = s->streams[i];
        mxf_write_track(s, st, type);
        mxf_write_sequence(s, st, type);
        mxf_write_structural_component(s, st, type);
1110 1111

        if (type == SourcePackage) {
1112
            MXFStreamContext *sc = st->priv_data;
1113
            mxf_essence_container_uls[sc->index].write_desc(s, st);
1114 1115 1116 1117
        }
    }
}

1118 1119
static int mxf_write_essence_container_data(AVFormatContext *s)
{
1120
    AVIOContext *pb = s->pb;
1121 1122

    mxf_write_metadata_key(pb, 0x012300);
1123
    klv_encode_ber_length(pb, 72);
1124 1125 1126 1127 1128

    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
1129
    mxf_write_umid(s, 1);
1130 1131

    mxf_write_local_tag(pb, 4, 0x3F07); // BodySID
1132
    avio_wb32(pb, 1);
1133

1134
    mxf_write_local_tag(pb, 4, 0x3F06); // IndexSID
1135
    avio_wb32(pb, 2);
1136

1137 1138 1139
    return 0;
}

1140 1141
static int mxf_write_header_metadata_sets(AVFormatContext *s)
{
1142
    mxf_write_preface(s);
1143 1144
    mxf_write_identification(s);
    mxf_write_content_storage(s);
1145 1146
    mxf_write_package(s, MaterialPackage);
    mxf_write_package(s, SourcePackage);
1147
    mxf_write_essence_container_data(s);
1148 1149 1150
    return 0;
}

1151
static unsigned klv_fill_size(uint64_t size)
1152
{
1153
    unsigned pad = KAG_SIZE - (size & (KAG_SIZE-1));
1154
    if (pad < 20) // smallest fill item possible
1155 1156 1157 1158 1159
        return pad + KAG_SIZE;
    else
        return pad & (KAG_SIZE-1);
}

1160
static void mxf_write_index_table_segment(AVFormatContext *s)
1161 1162
{
    MXFContext *mxf = s->priv_data;
1163
    AVIOContext *pb = s->pb;
1164
    int i, j, temporal_reordering = 0;
1165
    int key_index = mxf->last_key_index;
1166 1167 1168

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1169
    if (!mxf->edit_units_count && !mxf->edit_unit_byte_count)
1170 1171
        return;

1172
    avio_write(pb, index_table_segment_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1173 1174

    if (mxf->edit_unit_byte_count) {
1175
        klv_encode_ber_length(pb, 80);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1176
    } else {
1177 1178
        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
1179
    }
1180 1181 1182 1183 1184 1185 1186

    // 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);
1187 1188
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
1189 1190 1191

    // index start position
    mxf_write_local_tag(pb, 8, 0x3F0C);
1192
    avio_wb64(pb, mxf->last_indexed_edit_unit);
1193 1194 1195

    // index duration
    mxf_write_local_tag(pb, 8, 0x3F0D);
1196
    if (mxf->edit_unit_byte_count)
1197
        avio_wb64(pb, 0); // index table covers whole container
1198
    else
1199
        avio_wb64(pb, mxf->edit_units_count);
1200 1201 1202

    // edit unit byte count
    mxf_write_local_tag(pb, 4, 0x3F05);
1203
    avio_wb32(pb, mxf->edit_unit_byte_count);
1204 1205 1206

    // index sid
    mxf_write_local_tag(pb, 4, 0x3F06);
1207
    avio_wb32(pb, 2);
1208 1209 1210

    // body sid
    mxf_write_local_tag(pb, 4, 0x3F07);
1211
    avio_wb32(pb, 1);
1212

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1213
    if (!mxf->edit_unit_byte_count) {
1214 1215
        // real slice count - 1
        mxf_write_local_tag(pb, 1, 0x3F08);
1216
        avio_w8(pb, mxf->slice_count);
1217

1218 1219
        // delta entry array
        mxf_write_local_tag(pb, 8 + (s->nb_streams+1)*6, 0x3F09);
1220 1221
        avio_wb32(pb, s->nb_streams+1); // num of entries
        avio_wb32(pb, 6);               // size of one entry
1222
        // write system item delta entry
1223 1224 1225
        avio_w8(pb, 0);
        avio_w8(pb, 0); // slice entry
        avio_wb32(pb, 0); // element delta
1226 1227 1228
        for (i = 0; i < s->nb_streams; i++) {
            AVStream *st = s->streams[i];
            MXFStreamContext *sc = st->priv_data;
1229
            avio_w8(pb, sc->temporal_reordering);
1230 1231 1232
            if (sc->temporal_reordering)
                temporal_reordering = 1;
            if (i == 0) { // video track
1233 1234
                avio_w8(pb, 0); // slice number
                avio_wb32(pb, KAG_SIZE); // system item size including klv fill
1235 1236 1237
            } else { // audio track
                unsigned audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
                audio_frame_size += klv_fill_size(audio_frame_size);
1238 1239
                avio_w8(pb, 1);
                avio_wb32(pb, (i-1)*audio_frame_size); // element delta
1240
            }
1241
        }
1242

1243
        mxf_write_local_tag(pb, 8 + mxf->edit_units_count*(11+mxf->slice_count*4), 0x3F0A);
1244 1245
        avio_wb32(pb, mxf->edit_units_count);  // num of entries
        avio_wb32(pb, 11+mxf->slice_count*4);  // size of one entry
1246

1247
        for (i = 0; i < mxf->edit_units_count; i++) {
1248
            int temporal_offset = 0;
1249 1250 1251 1252 1253 1254

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

1255
            if (temporal_reordering) {
1256 1257 1258 1259 1260
                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;
1261
                    }
1262 1263 1264
                    if (j == mxf->edit_units_count)
                        av_log(s, AV_LOG_WARNING, "missing frames\n");
                    temporal_offset = j - key_index - pic_num_in_gop;
1265
                }
1266
            }
1267
            avio_w8(pb, temporal_offset);
1268 1269

            if ((mxf->index_entries[i].flags & 0x30) == 0x30) { // back and forward prediction
1270
                avio_w8(pb, mxf->last_key_index - i);
1271
            } else {
1272
                avio_w8(pb, key_index - i); // key frame offset
1273 1274 1275
                if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward
                    mxf->last_key_index = key_index;
            }
1276 1277 1278 1279

            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
1280
            avio_w8(pb, mxf->index_entries[i].flags);
1281
            // stream offset
1282
            avio_wb64(pb, mxf->index_entries[i].offset);
1283
            if (s->nb_streams > 1)
1284
                avio_wb32(pb, mxf->index_entries[i].slice_offset);
1285
        }
1286

1287 1288 1289
        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
1290
    }
1291 1292
}

1293 1294
static void mxf_write_klv_fill(AVFormatContext *s)
{
1295
    unsigned pad = klv_fill_size(avio_tell(s->pb));
1296
    if (pad) {
1297
        avio_write(s->pb, klv_fill_key, 16);
1298 1299
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
1300
        ffio_fill(s->pb, 0, pad);
1301
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
1302 1303 1304
    }
}

1305
static int mxf_write_partition(AVFormatContext *s, int bodysid,
1306
                                int indexsid,
1307
                                const uint8_t *key, int write_metadata)
1308 1309
{
    MXFContext *mxf = s->priv_data;
1310
    AVIOContext *pb = s->pb;
1311
    int64_t header_byte_count_offset;
1312
    unsigned index_byte_count = 0;
1313
    uint64_t partition_offset = avio_tell(pb);
1314
    int err;
1315

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1316 1317 1318 1319
    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)
1320
        index_byte_count = 80;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1321 1322

    if (index_byte_count) {
1323 1324 1325
        // add encoded ber length
        index_byte_count += 16 + klv_ber_length(index_byte_count);
        index_byte_count += klv_fill_size(index_byte_count);
1326 1327 1328
    }

    if (!memcmp(key, body_partition_key, 16)) {
1329 1330 1331 1332 1333
        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;
        }
1334
        mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset;
1335
    }
1336

1337
    // write klv
1338
    avio_write(pb, key, 16);
1339
    klv_encode_ber_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
1340 1341

    // write partition value
1342 1343 1344
    avio_wb16(pb, 1); // majorVersion
    avio_wb16(pb, 2); // minorVersion
    avio_wb32(pb, KAG_SIZE); // KAGSize
1345

1346
    avio_wb64(pb, partition_offset); // ThisPartition
1347 1348

    if (!memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
1349
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition
1350
    else if (!memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
1351
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
1352
    else
1353
        avio_wb64(pb, 0);
1354

1355
    avio_wb64(pb, mxf->footer_partition_offset); // footerPartition
1356 1357

    // set offset
1358
    header_byte_count_offset = avio_tell(pb);
1359
    avio_wb64(pb, 0); // headerByteCount, update later
1360

1361
    // indexTable
1362 1363
    avio_wb64(pb, index_byte_count); // indexByteCount
    avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
1364 1365

    // BodyOffset
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1366
    if (bodysid && mxf->edit_units_count && mxf->body_partitions_count) {
1367
        avio_wb64(pb, mxf->body_offset);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1368
    } else
1369
        avio_wb64(pb, 0);
1370

1371
    avio_wb32(pb, bodysid); // bodySID
1372 1373

    // operational pattern
1374
    avio_write(pb, op1a_ul, 16);
1375 1376

    // essence container
1377
    mxf_write_essence_container_refs(s);
1378 1379 1380

    if (write_metadata) {
        // mark the start of the headermetadata and calculate metadata size
1381
        int64_t pos, start;
1382 1383
        unsigned header_byte_count;

1384
        mxf_write_klv_fill(s);
1385
        start = avio_tell(s->pb);
1386 1387
        mxf_write_primer_pack(s);
        mxf_write_header_metadata_sets(s);
1388
        pos = avio_tell(s->pb);
1389
        header_byte_count = pos - start + klv_fill_size(pos);
1390

1391
        // update header_byte_count
1392
        avio_seek(pb, header_byte_count_offset, SEEK_SET);
1393
        avio_wb64(pb, header_byte_count);
1394
        avio_seek(pb, pos, SEEK_SET);
1395 1396
    }

1397
    avio_flush(pb);
1398 1399

    return 0;
1400 1401
}

1402 1403 1404 1405 1406 1407 1408
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;
1409
    int frame_size = 0;
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419

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

1420
    if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) < 0)
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
        return -1;

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

1461 1462
    sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
    sc->aspect_ratio = (AVRational){ 16, 9 };
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479

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

1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
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) {
1514
            av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n");
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
            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;

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

1550 1551 1552 1553 1554 1555 1556 1557 1558
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
1559 1560
    { 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
1561 1562 1563 1564
};

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

1567 1568
    if (avctx->profile == 4) { // Main
        if (avctx->level == 8) // Main
1569
            return &mxf_mpeg2_codec_uls[0+long_gop];
1570
        else if (avctx->level == 4) // High
1571
            return &mxf_mpeg2_codec_uls[4+long_gop];
1572 1573
        else if (avctx->level == 6) // High 14
            return &mxf_mpeg2_codec_uls[8+long_gop];
1574 1575
    } else if (avctx->profile == 0) { // 422
        if (avctx->level == 5) // Main
1576
            return &mxf_mpeg2_codec_uls[2+long_gop];
1577
        else if (avctx->level == 2) // High
1578
            return &mxf_mpeg2_codec_uls[6+long_gop];
1579 1580 1581 1582
    }
    return NULL;
}

1583 1584
static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
                                 AVPacket *pkt, MXFIndexEntry *e)
1585 1586 1587 1588 1589 1590 1591
{
    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];
1592
        if (c == 0x1b5) {
1593
            if ((pkt->data[i+1] & 0xf0) == 0x10) { // seq ext
1594 1595
                st->codec->profile = pkt->data[i+1] & 0x07;
                st->codec->level   = pkt->data[i+2] >> 4;
1596 1597
            } else if (i + 5 < pkt->size && (pkt->data[i+1] & 0xf0) == 0x80) { // pict coding ext
                sc->interlaced = !(pkt->data[i+5] & 0x80); // progressive frame
1598 1599
                if (sc->interlaced)
                    sc->field_dominance = 1 + !(pkt->data[i+4] & 0x80); // top field first
1600 1601
                break;
            }
1602
        } else if (c == 0x1b8) { // gop
1603 1604
            if (pkt->data[i+4]>>6 & 0x01) { // closed
                sc->closed_gop = 1;
1605 1606
                if (e->flags & 0x40) // sequence header present
                    e->flags |= 0x80; // random access
1607
            }
1608
        } else if (c == 0x1b3) { // seq
1609
            e->flags |= 0x40;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1610 1611 1612 1613 1614 1615 1616 1617
            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);
            }
1618 1619
        } else if (c == 0x100) { // pic
            int pict_type = (pkt->data[i+2]>>3) & 0x07;
1620
            e->temporal_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
1621
            if (pict_type == 2) { // P frame
1622
                e->flags |= 0x22;
1623
                sc->closed_gop = 0; // reset closed gop, don't matter anymore
1624
            } else if (pict_type == 3) { // B frame
1625
                if (sc->closed_gop)
1626
                    e->flags |= 0x13; // only backward prediction
1627
                else
1628
                    e->flags |= 0x33;
1629 1630 1631 1632 1633
                sc->temporal_reordering = -1;
            } else if (!pict_type) {
                av_log(s, AV_LOG_ERROR, "error parsing mpeg2 frame\n");
                return 0;
            }
1634 1635
        }
    }
1636
    if (s->oformat != &ff_mxf_d10_muxer)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1637
        sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codec);
1638 1639 1640
    return !!sc->codec_ul;
}

1641 1642
static uint64_t mxf_parse_timestamp(time_t timestamp)
{
1643
    struct tm *time = gmtime(&timestamp);
1644 1645
    if (!time)
        return 0;
1646 1647 1648 1649 1650 1651 1652 1653
    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;
}

1654 1655 1656
static void mxf_gen_umid(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
1657
    uint32_t seed = av_get_random_seed();
1658 1659 1660 1661 1662
    uint64_t umid = seed + 0x5294713400000000LL;

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

1663
    mxf->instance_number = seed & 0xFFFFFF;
1664 1665
}

1666
static int mxf_write_header(AVFormatContext *s)
1667 1668
{
    MXFContext *mxf = s->priv_data;
1669
    int i, ret;
1670
    uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
1671
    const MXFSamplesPerFrame *spf = NULL;
1672 1673
    AVDictionaryEntry *t;
    int64_t timestamp = 0;
1674
    AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
1675

1676 1677 1678
    if (!s->nb_streams)
        return -1;

1679 1680
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
1681
        MXFStreamContext *sc = av_mallocz(sizeof(*sc));
1682 1683 1684
        if (!sc)
            return AVERROR(ENOMEM);
        st->priv_data = sc;
1685

1686 1687 1688 1689 1690
        if ((i == 0) ^ (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)) {
            av_log(s, AV_LOG_ERROR, "there must be exactly one video stream and it must be the first one\n");
            return -1;
        }

1691
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
1692
            AVRational rate, tbc = st->codec->time_base;
1693 1694
            // Default component depth to 8
            sc->component_depth = 8;
1695
            mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num;
1696
            spf = ff_mxf_get_samples_per_frame(s, tbc);
1697
            if (!spf) {
1698 1699 1700
                av_log(s, AV_LOG_ERROR, "Unsupported video frame rate %d/%d\n",
                       tbc.den, tbc.num);
                return AVERROR(EINVAL);
1701
            }
1702
            mxf->time_base = spf->time_base;
1703
            rate = av_inv_q(mxf->time_base);
1704
            avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
1705 1706 1707 1708
            if (!tcr)
                tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
            if (tcr)
                ret = av_timecode_init_from_string(&mxf->tc, rate, tcr->value, s);
1709 1710 1711 1712
            else
                ret = av_timecode_init(&mxf->tc, rate, 0, 0, s);
            if (ret < 0)
                return ret;
1713
            sc->video_bit_rate = st->codec->bit_rate ? st->codec->bit_rate : st->codec->rc_max_rate;
1714
            if (s->oformat == &ff_mxf_d10_muxer) {
1715
                if (sc->video_bit_rate == 50000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1716 1717
                    if (mxf->time_base.den == 25) sc->index = 3;
                    else                          sc->index = 5;
1718
                } else if (sc->video_bit_rate == 40000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1719 1720
                    if (mxf->time_base.den == 25) sc->index = 7;
                    else                          sc->index = 9;
1721
                } else if (sc->video_bit_rate == 30000000) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1722 1723
                    if (mxf->time_base.den == 25) sc->index = 11;
                    else                          sc->index = 13;
1724
                } else {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1725 1726 1727 1728 1729
                    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
1730
                mxf->edit_unit_byte_count += 16 + 4 + (uint64_t)sc->video_bit_rate *
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1731 1732
                    mxf->time_base.num / (8*mxf->time_base.den);
                mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
1733
                mxf->edit_unit_byte_count += 16 + 4 + 4 + spf->samples_per_frame[0]*8*4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1734 1735
                mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
            }
1736
        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
1737 1738 1739 1740
            if (st->codec->sample_rate != 48000) {
                av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
                return -1;
            }
1741
            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
1742
            if (s->oformat == &ff_mxf_d10_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1743 1744 1745 1746
                if (st->index != 1) {
                    av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n");
                    return -1;
                }
1747 1748
                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
1749 1750 1751 1752
                    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;
            } else
1753
            mxf->slice_count = 1;
1754
        }
1755

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1756
        if (!sc->index) {
1757 1758 1759 1760 1761 1762
            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
1763
        }
1764

1765
        sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
1766

1767 1768
        memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15);
        sc->track_essence_element_key[15] = present[sc->index];
1769
        PRINT_KEY(s, "track essence element key", sc->track_essence_element_key);
1770 1771 1772 1773

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

1776
    if (s->oformat == &ff_mxf_d10_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1777 1778 1779
        mxf->essence_container_count = 1;
    }

1780
    if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
1781 1782
        mxf_gen_umid(s);

1783 1784 1785 1786
    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];
1787 1788 1789 1790
        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);
1791 1792
    }

1793 1794
    if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
        timestamp = ff_iso8601_to_unix_time(t->value);
1795 1796
    if (timestamp)
        mxf->timestamp = mxf_parse_timestamp(timestamp);
1797 1798 1799 1800 1801 1802 1803 1804
    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);
1805
    mxf->timecode_track->index = -1;
1806

1807
    if (!spf)
1808
        spf = ff_mxf_get_samples_per_frame(s, (AVRational){ 1, 25 });
1809

1810
    if (ff_audio_interleave_init(s, spf->samples_per_frame, mxf->time_base) < 0)
1811 1812
        return -1;

1813 1814 1815
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1816 1817 1818 1819 1820 1821
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;
1822
    AVIOContext *pb = s->pb;
1823
    unsigned frame;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1824 1825
    uint32_t time_code;

1826
    frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1827 1828

    // write system metadata pack
1829
    avio_write(pb, system_metadata_pack_key, 16);
1830
    klv_encode_ber4_length(pb, 57);
1831 1832 1833 1834
    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
1835
    avio_wb16(pb, (mxf->tc.start + frame) & 0xFFFF); // continuity count, supposed to overflow
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1836
    if (mxf->essence_container_count > 1)
1837
        avio_write(pb, multiple_desc_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1838 1839
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
1840
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1841
    }
1842 1843 1844
    avio_w8(pb, 0);
    avio_wb64(pb, 0);
    avio_wb64(pb, 0); // creation date/time stamp
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1845

1846
    avio_w8(pb, 0x81); // SMPTE 12M time code
1847
    time_code = av_timecode_get_smpte_from_framenum(&mxf->tc, frame);
1848 1849 1850
    avio_wb32(pb, time_code);
    avio_wb32(pb, 0); // binary group data
    avio_wb64(pb, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1851 1852

    // write system metadata package set
1853
    avio_write(pb, system_metadata_package_set_key, 16);
1854
    klv_encode_ber4_length(pb, 35);
1855 1856
    avio_w8(pb, 0x83); // UMID
    avio_wb16(pb, 0x20);
1857
    mxf_write_umid(s, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1858 1859
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1860 1861 1862
static void mxf_write_d10_video_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
1863
    AVIOContext *pb = s->pb;
1864 1865
    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
1866 1867 1868 1869 1870 1871 1872
        (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);
1873
    avio_write(pb, pkt->data, pkt->size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1874 1875 1876 1877

    // ensure CBR muxing by padding to correct video frame size
    pad = packet_size - pkt->size - 16 - 4;
    if (pad > 20) {
1878
        avio_write(s->pb, klv_fill_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1879 1880
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
Paul B Mahol's avatar
Paul B Mahol committed
1881
        ffio_fill(s->pb, 0, pad);
1882
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1883 1884
    } else {
        av_log(s, AV_LOG_WARNING, "cannot fill d-10 video packet\n");
Paul B Mahol's avatar
Paul B Mahol committed
1885
        ffio_fill(s->pb, 0, pad);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1886 1887 1888 1889 1890 1891
    }
}

static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
1892
    AVIOContext *pb = s->pb;
1893
    int frame_size = pkt->size / st->codec->block_align;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1894 1895 1896 1897 1898 1899
    uint8_t *samples = pkt->data;
    uint8_t *end = pkt->data + pkt->size;
    int i;

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

1900 1901 1902
    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
1903 1904 1905 1906

    while (samples < end) {
        for (i = 0; i < st->codec->channels; i++) {
            uint32_t sample;
1907
            if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE) {
1908
                sample = AV_RL24(samples)<< 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1909 1910
                samples += 3;
            } else {
1911
                sample = AV_RL16(samples)<<12;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1912 1913
                samples += 2;
            }
1914
            avio_wl32(pb, sample | i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1915 1916
        }
        for (; i < 8; i++)
1917
            avio_wl32(pb, i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1918 1919 1920
    }
}

1921
static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
1922
{
1923
    MXFContext *mxf = s->priv_data;
1924
    AVIOContext *pb = s->pb;
1925 1926
    AVStream *st = s->streams[pkt->stream_index];
    MXFStreamContext *sc = st->priv_data;
1927
    MXFIndexEntry ie = {0};
1928
    int err;
1929

1930
    if (!mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) {
1931 1932 1933
        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;
1934
            av_log(s, AV_LOG_ERROR, "could not allocate index entries\n");
1935
            return err;
1936 1937 1938
        }
    }

1939
    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1940
        if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
1941 1942
            av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
            return -1;
1943
        }
1944
    } else if (st->codec->codec_id == AV_CODEC_ID_DNXHD) {
1945 1946 1947 1948
        if (!mxf_parse_dnxhd_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
            return -1;
        }
1949
    } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) {
1950 1951 1952 1953
        if (!mxf_parse_dv_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
            return -1;
        }
1954 1955 1956
    }

    if (!mxf->header_written) {
1957
        if (mxf->edit_unit_byte_count) {
1958 1959
            if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0)
                return err;
1960 1961 1962
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        } else {
1963 1964
            if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0)
                return err;
1965
        }
1966 1967 1968
        mxf->header_written = 1;
    }

1969
    if (st->index == 0) {
1970 1971
        if (!mxf->edit_unit_byte_count &&
            (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) &&
1972
            !(ie.flags & 0x33)) { // I frame, Gop start
1973
            mxf_write_klv_fill(s);
1974 1975
            if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0)
                return err;
1976 1977 1978 1979
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1980
        mxf_write_klv_fill(s);
1981
        mxf_write_system_item(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1982

1983 1984
        if (!mxf->edit_unit_byte_count) {
            mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
1985 1986
            mxf->index_entries[mxf->edit_units_count].flags = ie.flags;
            mxf->index_entries[mxf->edit_units_count].temporal_ref = ie.temporal_ref;
1987 1988
            mxf->body_offset += KAG_SIZE; // size of system element
        }
1989
        mxf->edit_units_count++;
1990
    } else if (!mxf->edit_unit_byte_count && st->index == 1) {
1991 1992
        mxf->index_entries[mxf->edit_units_count-1].slice_offset =
            mxf->body_offset - mxf->index_entries[mxf->edit_units_count-1].offset;
1993 1994
    }

1995
    mxf_write_klv_fill(s);
1996
    avio_write(pb, sc->track_essence_element_key, 16); // write key
1997
    if (s->oformat == &ff_mxf_d10_muxer) {
1998
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
1999 2000 2001 2002 2003
            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
2004
        avio_write(pb, pkt->data, pkt->size);
2005 2006
        mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size);
    }
2007

2008
    avio_flush(pb);
2009

2010 2011 2012
    return 0;
}

2013 2014 2015
static void mxf_write_random_index_pack(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2016
    AVIOContext *pb = s->pb;
2017
    uint64_t pos = avio_tell(pb);
2018
    int i;
2019

2020
    avio_write(pb, random_index_pack_key, 16);
2021
    klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count);
2022

2023
    if (mxf->edit_unit_byte_count)
2024
        avio_wb32(pb, 1); // BodySID of header partition
2025
    else
2026 2027
        avio_wb32(pb, 0);
    avio_wb64(pb, 0); // offset of header partition
2028

2029
    for (i = 0; i < mxf->body_partitions_count; i++) {
2030 2031
        avio_wb32(pb, 1); // BodySID
        avio_wb64(pb, mxf->body_partition_offset[i]);
2032 2033
    }

2034 2035
    avio_wb32(pb, 0); // BodySID of footer partition
    avio_wb64(pb, mxf->footer_partition_offset);
2036

2037
    avio_wb32(pb, avio_tell(pb) - pos + 4);
2038 2039
}

2040
static int mxf_write_footer(AVFormatContext *s)
2041
{
2042
    MXFContext *mxf = s->priv_data;
2043
    AVIOContext *pb = s->pb;
2044
    int err;
2045

2046 2047
    mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;

2048
    mxf_write_klv_fill(s);
2049
    mxf->footer_partition_offset = avio_tell(pb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2050
    if (mxf->edit_unit_byte_count) { // no need to repeat index
2051 2052
        if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0)
            return err;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2053
    } else {
2054 2055
        if ((err = mxf_write_partition(s, 0, 2, footer_partition_key, 0)) < 0)
            return err;
2056 2057
        mxf_write_klv_fill(s);
        mxf_write_index_table_segment(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2058
    }
2059

2060
    mxf_write_klv_fill(s);
2061 2062
    mxf_write_random_index_pack(s);

2063
    if (s->pb->seekable) {
2064
        avio_seek(pb, 0, SEEK_SET);
2065
        if (mxf->edit_unit_byte_count) {
2066 2067
            if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0)
                return err;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2068 2069
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
2070
        } else {
2071 2072
            if ((err = mxf_write_partition(s, 0, 0, header_closed_partition_key, 1)) < 0)
                return err;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2073
        }
2074
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2075 2076 2077

    ff_audio_interleave_close(s);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2078
    av_freep(&mxf->index_entries);
2079
    av_freep(&mxf->body_partition_offset);
2080 2081
    av_freep(&mxf->timecode_track->priv_data);
    av_freep(&mxf->timecode_track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2082

2083
    mxf_free(s);
2084

2085 2086
    return 0;
}
2087

2088
static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
2089
{
2090 2091 2092 2093
    int i, stream_count = 0;

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

    if (stream_count && (s->nb_streams == stream_count || flush)) {
2096
        AVPacketList *pktl = s->packet_buffer;
2097
        if (s->nb_streams != stream_count) {
2098
            AVPacketList *last = NULL;
2099
            // find last packet in edit unit
2100
            while (pktl) {
2101
                if (!stream_count || pktl->pkt.stream_index == 0)
2102
                    break;
2103
                last = pktl;
2104
                pktl = pktl->next;
2105
                stream_count--;
2106
            }
2107 2108 2109
            // purge packet queue
            while (pktl) {
                AVPacketList *next = pktl->next;
2110 2111 2112

                if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
                    s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
2113 2114 2115 2116
                av_free_packet(&pktl->pkt);
                av_freep(&pktl);
                pktl = next;
            }
2117 2118 2119 2120
            if (last)
                last->next = NULL;
            else {
                s->packet_buffer = NULL;
2121
                s->packet_buffer_end= NULL;
2122
                goto out;
2123 2124
            }
            pktl = s->packet_buffer;
2125 2126
        }

2127
        *out = pktl->pkt;
2128
        av_dlog(s, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts);
2129
        s->packet_buffer = pktl->next;
2130 2131 2132 2133
        if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
            s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
        if(!s->packet_buffer)
            s->packet_buffer_end= NULL;
2134
        av_freep(&pktl);
2135 2136
        return 1;
    } else {
2137
    out:
2138 2139 2140 2141 2142 2143 2144
        av_init_packet(out);
        return 0;
    }
}

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

2148 2149
    return next->dts > pkt->dts ||
        (next->dts == pkt->dts && sc->order < sc2->order);
2150 2151 2152 2153
}

static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
{
2154
    return ff_audio_rechunk_interleave(s, out, pkt, flush,
2155
                               mxf_interleave_get_packet, mxf_compare_timestamps);
2156 2157
}

2158
AVOutputFormat ff_mxf_muxer = {
2159
    .name              = "mxf",
2160
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
2161 2162 2163
    .mime_type         = "application/mxf",
    .extensions        = "mxf",
    .priv_data_size    = sizeof(MXFContext),
2164 2165
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2166 2167 2168 2169 2170
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
2171
};
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2172

2173
AVOutputFormat ff_mxf_d10_muxer = {
2174
    .name              = "mxf_d10",
2175
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"),
2176 2177
    .mime_type         = "application/mxf",
    .priv_data_size    = sizeof(MXFContext),
2178 2179
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2180 2181 2182 2183 2184
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2185
};