mxfenc.c 83 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 33 34
 *
 * 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
 */

//#define DEBUG

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

38
#include "libavutil/opt.h"
39
#include "libavutil/random_seed.h"
40
#include "libavutil/timecode.h"
41
#include "libavutil/avassert.h"
42
#include "libavcodec/bytestream.h"
43
#include "libavcodec/dnxhddata.h"
44
#include "audiointerleave.h"
45
#include "avformat.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 80
} MXFStreamContext;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

485
    local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch);
486

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

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

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

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

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

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

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

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

532
static void mxf_write_essence_container_refs(AVFormatContext *s)
533
{
534
    MXFContext *c = s->priv_data;
535
    AVIOContext *pb = s->pb;
536
    int i;
537

Baptiste Coudurier's avatar
Baptiste Coudurier committed
538 539 540
    mxf_write_refs_count(pb, c->essence_container_count);
    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
541
        MXFStreamContext *sc = s->streams[i]->priv_data;
542
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
543
    }
544 545
}

546 547 548
static void mxf_write_preface(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
549
    AVIOContext *pb = s->pb;
550 551 552 553 554 555 556 557 558 559

    mxf_write_metadata_key(pb, 0x012f00);
    PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
    klv_encode_ber_length(pb, 130 + 16 * mxf->essence_container_count);

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

560
    // last modified date
561
    mxf_write_local_tag(pb, 8, 0x3B02);
562
    avio_wb64(pb, mxf->timestamp);
563 564 565

    // write version
    mxf_write_local_tag(pb, 2, 0x3B05);
566
    avio_wb16(pb, 258); // v1.2
567 568 569 570 571 572 573 574 575 576

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

577
    // operational pattern
578
    mxf_write_local_tag(pb, 16, 0x3B09);
579
    avio_write(pb, op1a_ul, 16);
580 581 582

    // write essence_container_refs
    mxf_write_local_tag(pb, 8 + 16 * mxf->essence_container_count, 0x3B0A);
583
    mxf_write_essence_container_refs(s);
584 585 586

    // write dm_scheme_refs
    mxf_write_local_tag(pb, 8, 0x3B0B);
587
    avio_wb64(pb, 0);
588 589
}

590
/*
591
 * Write a local tag containing an ascii string as utf-16
592
 */
593
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
594
{
595
    int i, size = strlen(value);
596
    mxf_write_local_tag(pb, size*2, tag);
597
    for (i = 0; i < size; i++)
598
        avio_wb16(pb, value[i]);
599 600
}

601 602
static void mxf_write_identification(AVFormatContext *s)
{
603
    MXFContext *mxf = s->priv_data;
604
    AVIOContext *pb = s->pb;
605
    const char *company = "FFmpeg";
606
    const char *product = "OP1a Muxer";
607
    const char *version;
608
    int length;
609 610 611 612

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
613
    version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ?
614
        "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
615
    length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16
616 617 618 619 620 621
    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
622

623 624 625 626
    // write generation uid
    mxf_write_local_tag(pb, 16, 0x3C09);
    mxf_write_uuid(pb, Identification, 1);

627 628
    mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
    mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
629
    mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
630 631 632 633 634

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

635
    // modification date
636
    mxf_write_local_tag(pb, 8, 0x3C06);
637
    avio_wb64(pb, mxf->timestamp);
638 639 640 641
}

static void mxf_write_content_storage(AVFormatContext *s)
{
642
    AVIOContext *pb = s->pb;
643 644 645

    mxf_write_metadata_key(pb, 0x011800);
    PRINT_KEY(s, "content storage key", pb->buf_ptr - 16);
646
    klv_encode_ber_length(pb, 92);
647 648 649 650 651

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

653 654 655 656 657
    // 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);
658 659 660 661 662

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

665
static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
666
{
667
    MXFContext *mxf = s->priv_data;
668
    AVIOContext *pb = s->pb;
669
    MXFStreamContext *sc = st->priv_data;
670 671 672 673 674 675 676

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

680 681
    // write track id
    mxf_write_local_tag(pb, 4, 0x4801);
682
    avio_wb32(pb, st->index+2);
683

684
    // write track number
685
    mxf_write_local_tag(pb, 4, 0x4804);
686
    if (type == MaterialPackage)
687
        avio_wb32(pb, 0); // track number of material package is 0
688
    else
689
        avio_write(pb, sc->track_essence_element_key + 12, 4);
690 691

    mxf_write_local_tag(pb, 8, 0x4B01);
692 693
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
694 695 696

    // write origin
    mxf_write_local_tag(pb, 8, 0x4B02);
697
    avio_wb64(pb, 0);
698 699 700

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

704 705 706
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)
707
{
708
    MXFContext *mxf = s->priv_data;
709
    AVIOContext *pb = s->pb;
710

711 712
    // find data define uls
    mxf_write_local_tag(pb, 16, 0x0201);
713
    if (st == mxf->timecode_track)
714
        avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
715 716
    else {
        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
717
        avio_write(pb, data_def_ul->uid, 16);
718
    }
719 720 721

    // write duration
    mxf_write_local_tag(pb, 8, 0x0202);
722
    avio_wb64(pb, mxf->duration);
723 724
}

725
static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
726
{
727
    MXFContext *mxf = s->priv_data;
728
    AVIOContext *pb = s->pb;
729
    enum MXFMetadataSetType component;
730 731 732 733 734 735

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

    PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
739
    mxf_write_common_fields(s, st);
740 741 742 743

    // write structural component
    mxf_write_local_tag(pb, 16 + 8, 0x1001);
    mxf_write_refs_count(pb, 1);
744 745 746
    if (st == mxf->timecode_track)
        component = TimecodeComponent;
    else
747 748 749
        component = SourceClip;
    if (type == SourcePackage)
        component += TypeBottom;
750 751 752
    mxf_write_uuid(pb, component, st->index);
}

753
static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
754 755
{
    MXFContext *mxf = s->priv_data;
756
    AVIOContext *pb = s->pb;
757 758 759 760 761 762

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

    // UID
    mxf_write_local_tag(pb, 16, 0x3C0A);
763 764
    mxf_write_uuid(pb, type == MaterialPackage ? TimecodeComponent :
                   TimecodeComponent + TypeBottom, st->index);
765 766 767 768 769

    mxf_write_common_fields(s, st);

    // Start Time Code
    mxf_write_local_tag(pb, 8, 0x1501);
770
    avio_wb64(pb, mxf->tc.start);
771 772 773

    // Rounded Time Code Base
    mxf_write_local_tag(pb, 2, 0x1502);
774
    avio_wb16(pb, mxf->timecode_base);
775 776 777

    // Drop Frame
    mxf_write_local_tag(pb, 1, 0x1503);
778
    avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
779 780
}

781
static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
782
{
783
    AVIOContext *pb = s->pb;
784 785 786 787 788 789 790 791
    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);
792
    mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index);
793 794

    PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
795
    mxf_write_common_fields(s, st);
796 797 798

    // write start_position
    mxf_write_local_tag(pb, 8, 0x1201);
799
    avio_wb64(pb, 0);
800

801
    // write source package uid, end of the reference
802 803
    mxf_write_local_tag(pb, 32, 0x1101);
    if (type == SourcePackage) {
804
        for (i = 0; i < 4; i++)
805
            avio_wb64(pb, 0);
806
    } else
807
        mxf_write_umid(s, 1);
808

809
    // write source track id
810 811
    mxf_write_local_tag(pb, 4, 0x1102);
    if (type == SourcePackage)
812
        avio_wb32(pb, 0);
813
    else
814
        avio_wb32(pb, st->index+2);
815 816
}

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

    mxf_write_metadata_key(pb, 0x014400);
    PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16);
    klv_encode_ber_length(pb, 64 + 16 * s->nb_streams);

    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);
834 835
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
836 837 838

    // write essence container ul
    mxf_write_local_tag(pb, 16, 0x3004);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
839 840
    if (mxf->essence_container_count > 1)
        ul = multiple_desc_ul;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
841 842 843 844
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
        ul = mxf_essence_container_uls[sc->index].container_ul;
    }
845
    avio_write(pb, ul, 16);
846 847 848 849

    // write sub descriptor refs
    mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01);
    mxf_write_refs_count(pb, s->nb_streams);
850
    for (i = 0; i < s->nb_streams; i++)
851 852 853
        mxf_write_uuid(pb, SubDescriptor, i);
}

854
static void mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
855
{
856
    MXFContext *mxf = s->priv_data;
857
    MXFStreamContext *sc = st->priv_data;
858
    AVIOContext *pb = s->pb;
859

860
    avio_write(pb, key, 16);
861
    klv_encode_ber4_length(pb, size+20+8+12+20);
862 863 864 865 866

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

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

869
    mxf_write_local_tag(pb, 8, 0x3001);
870 871
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
872

873
    mxf_write_local_tag(pb, 16, 0x3004);
874
    avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
875 876
}

877 878
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 };
879
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
880 881
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 };
882

883
static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
884
{
885
    MXFStreamContext *sc = st->priv_data;
886
    AVIOContext *pb = s->pb;
887
    int stored_height = (st->codec->height+15)/16*16;
888
    int display_height;
889
    int f1, f2;
890 891 892
    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;
893

894
    mxf_write_generic_desc(s, st, key, desc_size);
895 896

    mxf_write_local_tag(pb, 4, 0x3203);
897
    avio_wb32(pb, st->codec->width);
898 899

    mxf_write_local_tag(pb, 4, 0x3202);
900
    avio_wb32(pb, stored_height>>sc->interlaced);
901

902
    mxf_write_local_tag(pb, 4, 0x3209);
903
    avio_wb32(pb, st->codec->width);
904

905 906 907 908 909 910 911
    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;

912
    mxf_write_local_tag(pb, 4, 0x3208);
913
    avio_wb32(pb, display_height>>sc->interlaced);
914

915 916
    // component depth
    mxf_write_local_tag(pb, 4, 0x3301);
917
    avio_wb32(pb, sc->component_depth);
918 919 920

    // horizontal subsampling
    mxf_write_local_tag(pb, 4, 0x3302);
921
    avio_wb32(pb, 2);
922

923 924
    // frame layout
    mxf_write_local_tag(pb, 1, 0x320C);
925
    avio_w8(pb, sc->interlaced);
926

927 928
    // video line map
    switch (st->codec->height) {
929
    case  576: f1 = 23; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
930
    case  608: f1 =  7; f2 = 320; break;
931
    case  480: f1 = 20; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
932 933 934 935 936 937 938 939 940 941 942
    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;
    }

943
    mxf_write_local_tag(pb, 12+sc->interlaced*4, 0x320D);
944 945 946
    avio_wb32(pb, sc->interlaced ? 2 : 1);
    avio_wb32(pb, 4);
    avio_wb32(pb, f1);
947
    if (sc->interlaced)
948
        avio_wb32(pb, f2);
949

950
    mxf_write_local_tag(pb, 8, 0x320E);
951 952
    avio_wb32(pb, sc->aspect_ratio.num);
    avio_wb32(pb, sc->aspect_ratio.den);
953 954

    mxf_write_local_tag(pb, 16, 0x3201);
955
    avio_write(pb, *sc->codec_ul, 16);
956 957 958 959 960 961

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

962 963
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
964 965
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
{
966
    mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
967 968
}

969 970
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
{
971
    AVIOContext *pb = s->pb;
972
    int profile_and_level = (st->codec->profile<<4) | st->codec->level;
973

974
    mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5);
975 976 977

    // bit rate
    mxf_write_local_tag(pb, 4, 0x8000);
978
    avio_wb32(pb, st->codec->bit_rate);
979 980 981 982 983

    // profile and level
    mxf_write_local_tag(pb, 1, 0x8007);
    if (!st->codec->profile)
        profile_and_level |= 0x80; // escape bit
984
    avio_w8(pb, profile_and_level);
985 986 987
}

static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
988
{
989
    AVIOContext *pb = s->pb;
990

991
    mxf_write_generic_desc(s, st, key, size+5+12+8+8);
992

993
    // audio locked
994
    mxf_write_local_tag(pb, 1, 0x3D02);
995
    avio_w8(pb, 1);
996 997 998

    // write audio sampling rate
    mxf_write_local_tag(pb, 8, 0x3D03);
999 1000
    avio_wb32(pb, st->codec->sample_rate);
    avio_wb32(pb, 1);
1001 1002

    mxf_write_local_tag(pb, 4, 0x3D07);
1003
    avio_wb32(pb, st->codec->channels);
1004 1005

    mxf_write_local_tag(pb, 4, 0x3D01);
1006
    avio_wb32(pb, av_get_bits_per_sample(st->codec->codec_id));
1007 1008
}

1009
static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
1010
{
1011
    AVIOContext *pb = s->pb;
1012

1013
    mxf_write_generic_sound_common(s, st, key, size+6+8);
1014 1015

    mxf_write_local_tag(pb, 2, 0x3D0A);
1016
    avio_wb16(pb, st->codec->block_align);
1017 1018 1019

    // avg bytes per sec
    mxf_write_local_tag(pb, 4, 0x3D09);
1020
    avio_wb32(pb, st->codec->block_align*st->codec->sample_rate);
1021 1022
}

1023
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st)
1024
{
1025
    mxf_write_wav_common(s, st, mxf_wav_descriptor_key, 0);
1026
}
1027

1028 1029
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st)
{
1030
    mxf_write_wav_common(s, st, mxf_aes3_descriptor_key, 0);
1031 1032
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1033 1034
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st)
{
1035
    mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1036 1037
}

1038 1039
static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type)
{
1040
    MXFContext *mxf = s->priv_data;
1041
    AVIOContext *pb = s->pb;
1042
    int i, track_count = s->nb_streams+1;
1043 1044 1045 1046

    if (type == MaterialPackage) {
        mxf_write_metadata_key(pb, 0x013600);
        PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
1047
        klv_encode_ber_length(pb, 92 + 16*track_count);
1048 1049 1050
    } else {
        mxf_write_metadata_key(pb, 0x013700);
        PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
1051
        klv_encode_ber_length(pb, 112 + 16*track_count); // 20 bytes length for descriptor reference
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
    }

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

1065
    // package creation date
1066
    mxf_write_local_tag(pb, 8, 0x4405);
1067
    avio_wb64(pb, mxf->timestamp);
1068

1069
    // package modified date
1070
    mxf_write_local_tag(pb, 8, 0x4404);
1071
    avio_wb64(pb, mxf->timestamp);
1072 1073

    // write track refs
1074 1075
    mxf_write_local_tag(pb, track_count*16 + 8, 0x4403);
    mxf_write_refs_count(pb, track_count);
1076 1077
    mxf_write_uuid(pb, type == MaterialPackage ? Track :
                   Track + TypeBottom, -1); // timecode track
1078 1079 1080 1081 1082 1083
    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);
1084 1085 1086 1087 1088
        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
1089
    }
1090

1091 1092 1093 1094 1095
    // 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);

1096
    for (i = 0; i < s->nb_streams; i++) {
1097 1098 1099 1100
        AVStream *st = s->streams[i];
        mxf_write_track(s, st, type);
        mxf_write_sequence(s, st, type);
        mxf_write_structural_component(s, st, type);
1101 1102

        if (type == SourcePackage) {
1103
            MXFStreamContext *sc = st->priv_data;
1104
            mxf_essence_container_uls[sc->index].write_desc(s, st);
1105 1106 1107 1108
        }
    }
}

1109 1110
static int mxf_write_essence_container_data(AVFormatContext *s)
{
1111
    AVIOContext *pb = s->pb;
1112 1113

    mxf_write_metadata_key(pb, 0x012300);
1114
    klv_encode_ber_length(pb, 72);
1115 1116 1117 1118 1119

    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
1120
    mxf_write_umid(s, 1);
1121 1122

    mxf_write_local_tag(pb, 4, 0x3F07); // BodySID
1123
    avio_wb32(pb, 1);
1124

1125
    mxf_write_local_tag(pb, 4, 0x3F06); // IndexSID
1126
    avio_wb32(pb, 2);
1127

1128 1129 1130
    return 0;
}

1131 1132
static int mxf_write_header_metadata_sets(AVFormatContext *s)
{
1133
    mxf_write_preface(s);
1134 1135
    mxf_write_identification(s);
    mxf_write_content_storage(s);
1136 1137
    mxf_write_package(s, MaterialPackage);
    mxf_write_package(s, SourcePackage);
1138
    mxf_write_essence_container_data(s);
1139 1140 1141
    return 0;
}

1142
static unsigned klv_fill_size(uint64_t size)
1143
{
1144
    unsigned pad = KAG_SIZE - (size & (KAG_SIZE-1));
1145
    if (pad < 20) // smallest fill item possible
1146 1147 1148 1149 1150
        return pad + KAG_SIZE;
    else
        return pad & (KAG_SIZE-1);
}

1151
static void mxf_write_index_table_segment(AVFormatContext *s)
1152 1153
{
    MXFContext *mxf = s->priv_data;
1154
    AVIOContext *pb = s->pb;
1155
    int i, j, temporal_reordering = 0;
1156
    int key_index = mxf->last_key_index;
1157 1158 1159

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1160
    if (!mxf->edit_units_count && !mxf->edit_unit_byte_count)
1161 1162
        return;

1163
    avio_write(pb, index_table_segment_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1164 1165

    if (mxf->edit_unit_byte_count) {
1166
        klv_encode_ber_length(pb, 80);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1167 1168 1169 1170
    } else {
        klv_encode_ber_length(pb, 85 + 12+(s->nb_streams+1)*6 +
                              12+mxf->edit_units_count*(11+mxf->slice_count*4));
    }
1171 1172 1173 1174 1175 1176 1177

    // 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);
1178 1179
    avio_wb32(pb, mxf->time_base.den);
    avio_wb32(pb, mxf->time_base.num);
1180 1181 1182

    // index start position
    mxf_write_local_tag(pb, 8, 0x3F0C);
1183
    avio_wb64(pb, mxf->last_indexed_edit_unit);
1184 1185 1186

    // index duration
    mxf_write_local_tag(pb, 8, 0x3F0D);
1187
    if (mxf->edit_unit_byte_count)
1188
        avio_wb64(pb, 0); // index table covers whole container
1189
    else
1190
        avio_wb64(pb, mxf->edit_units_count);
1191 1192 1193

    // edit unit byte count
    mxf_write_local_tag(pb, 4, 0x3F05);
1194
    avio_wb32(pb, mxf->edit_unit_byte_count);
1195 1196 1197

    // index sid
    mxf_write_local_tag(pb, 4, 0x3F06);
1198
    avio_wb32(pb, 2);
1199 1200 1201

    // body sid
    mxf_write_local_tag(pb, 4, 0x3F07);
1202
    avio_wb32(pb, 1);
1203

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1204
    if (!mxf->edit_unit_byte_count) {
1205 1206
        // real slice count - 1
        mxf_write_local_tag(pb, 1, 0x3F08);
1207
        avio_w8(pb, mxf->slice_count);
1208

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

1234
        mxf_write_local_tag(pb, 8 + mxf->edit_units_count*(11+mxf->slice_count*4), 0x3F0A);
1235 1236
        avio_wb32(pb, mxf->edit_units_count);  // num of entries
        avio_wb32(pb, 11+mxf->slice_count*4);  // size of one entry
1237

1238
        for (i = 0; i < mxf->edit_units_count; i++) {
1239
            int temporal_offset = 0;
1240 1241 1242 1243 1244 1245

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

1246
            if (temporal_reordering) {
1247 1248 1249 1250 1251
                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;
1252
                    }
1253 1254 1255
                    if (j == mxf->edit_units_count)
                        av_log(s, AV_LOG_WARNING, "missing frames\n");
                    temporal_offset = j - key_index - pic_num_in_gop;
1256
                }
1257
            }
1258
            avio_w8(pb, temporal_offset);
1259 1260

            if ((mxf->index_entries[i].flags & 0x30) == 0x30) { // back and forward prediction
1261
                avio_w8(pb, mxf->last_key_index - i);
1262
            } else {
1263
                avio_w8(pb, key_index - i); // key frame offset
1264 1265 1266
                if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward
                    mxf->last_key_index = key_index;
            }
1267 1268 1269 1270

            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
1271
            avio_w8(pb, mxf->index_entries[i].flags);
1272
            // stream offset
1273
            avio_wb64(pb, mxf->index_entries[i].offset);
1274
            if (s->nb_streams > 1)
1275
                avio_wb32(pb, mxf->index_entries[i].slice_offset);
1276
        }
1277

1278 1279 1280
        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
1281
    }
1282 1283
}

1284 1285
static void mxf_write_klv_fill(AVFormatContext *s)
{
1286
    unsigned pad = klv_fill_size(avio_tell(s->pb));
1287
    if (pad) {
1288
        avio_write(s->pb, klv_fill_key, 16);
1289 1290
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
1291
        for (; pad; pad--)
1292
            avio_w8(s->pb, 0);
1293
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
1294 1295 1296
    }
}

1297
static void mxf_write_partition(AVFormatContext *s, int bodysid,
1298
                                int indexsid,
1299
                                const uint8_t *key, int write_metadata)
1300 1301
{
    MXFContext *mxf = s->priv_data;
1302
    AVIOContext *pb = s->pb;
1303
    int64_t header_byte_count_offset;
1304
    unsigned index_byte_count = 0;
1305
    uint64_t partition_offset = avio_tell(pb);
1306

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1307 1308 1309 1310
    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)
1311
        index_byte_count = 80;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1312 1313

    if (index_byte_count) {
1314 1315 1316
        // add encoded ber length
        index_byte_count += 16 + klv_ber_length(index_byte_count);
        index_byte_count += klv_fill_size(index_byte_count);
1317 1318 1319 1320 1321 1322 1323
    }

    if (!memcmp(key, body_partition_key, 16)) {
        mxf->body_partition_offset =
            av_realloc(mxf->body_partition_offset,
                       (mxf->body_partitions_count+1)*
                       sizeof(*mxf->body_partition_offset));
1324
        mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset;
1325
    }
1326

1327
    // write klv
1328
    avio_write(pb, key, 16);
1329 1330 1331
    klv_encode_ber_length(pb, 88 + 16 * mxf->essence_container_count);

    // write partition value
1332 1333 1334
    avio_wb16(pb, 1); // majorVersion
    avio_wb16(pb, 2); // minorVersion
    avio_wb32(pb, KAG_SIZE); // KAGSize
1335

1336
    avio_wb64(pb, partition_offset); // ThisPartition
1337 1338

    if (!memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
1339
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition
1340
    else if (!memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
1341
        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
1342
    else
1343
        avio_wb64(pb, 0);
1344

1345
    avio_wb64(pb, mxf->footer_partition_offset); // footerPartition
1346 1347

    // set offset
1348
    header_byte_count_offset = avio_tell(pb);
1349
    avio_wb64(pb, 0); // headerByteCount, update later
1350

1351
    // indexTable
1352 1353
    avio_wb64(pb, index_byte_count); // indexByteCount
    avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
1354 1355

    // BodyOffset
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1356
    if (bodysid && mxf->edit_units_count && mxf->body_partitions_count) {
1357
        avio_wb64(pb, mxf->body_offset);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1358
    } else
1359
        avio_wb64(pb, 0);
1360

1361
    avio_wb32(pb, bodysid); // bodySID
1362 1363

    // operational pattern
1364
    avio_write(pb, op1a_ul, 16);
1365 1366

    // essence container
1367
    mxf_write_essence_container_refs(s);
1368 1369 1370

    if (write_metadata) {
        // mark the start of the headermetadata and calculate metadata size
1371
        int64_t pos, start;
1372 1373
        unsigned header_byte_count;

1374
        mxf_write_klv_fill(s);
1375
        start = avio_tell(s->pb);
1376 1377
        mxf_write_primer_pack(s);
        mxf_write_header_metadata_sets(s);
1378
        pos = avio_tell(s->pb);
1379
        header_byte_count = pos - start + klv_fill_size(pos);
1380

1381
        // update header_byte_count
1382
        avio_seek(pb, header_byte_count_offset, SEEK_SET);
1383
        avio_wb64(pb, header_byte_count);
1384
        avio_seek(pb, pos, SEEK_SET);
1385 1386
    }

1387
    avio_flush(pb);
1388 1389
}

1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 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
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;
    unsigned int frame_size = 0;

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

    if ((i = ff_dnxhd_get_cid_table(cid)) < 0)
        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;
    }

    frame_size = ff_dnxhd_cid_table[i].frame_size;
1450 1451
    sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
    sc->aspect_ratio = (AVRational){ 16, 9 };
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468

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

1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
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) {
1503
            av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n");
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
            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;
}

1539 1540 1541 1542 1543 1544 1545 1546 1547
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
1548 1549
    { 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
1550 1551 1552 1553
};

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

1556 1557
    if (avctx->profile == 4) { // Main
        if (avctx->level == 8) // Main
1558
            return &mxf_mpeg2_codec_uls[0+long_gop];
1559
        else if (avctx->level == 4) // High
1560
            return &mxf_mpeg2_codec_uls[4+long_gop];
1561 1562
        else if (avctx->level == 6) // High 14
            return &mxf_mpeg2_codec_uls[8+long_gop];
1563 1564
    } else if (avctx->profile == 0) { // 422
        if (avctx->level == 5) // Main
1565
            return &mxf_mpeg2_codec_uls[2+long_gop];
1566
        else if (avctx->level == 2) // High
1567
            return &mxf_mpeg2_codec_uls[6+long_gop];
1568 1569 1570 1571
    }
    return NULL;
}

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

1630 1631
static uint64_t mxf_parse_timestamp(time_t timestamp)
{
1632
    struct tm *time = gmtime(&timestamp);
1633 1634
    if (!time)
        return 0;
1635 1636 1637 1638 1639 1640 1641 1642
    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;
}

1643 1644 1645
static void mxf_gen_umid(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
1646
    uint32_t seed = av_get_random_seed();
1647 1648 1649 1650 1651 1652 1653 1654
    uint64_t umid = seed + 0x5294713400000000LL;

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

    mxf->instance_number = seed;
}

1655
static int mxf_write_header(AVFormatContext *s)
1656 1657
{
    MXFContext *mxf = s->priv_data;
1658
    int i, ret;
1659
    uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
1660
    const MXFSamplesPerFrame *spf = NULL;
1661 1662
    AVDictionaryEntry *t;
    int64_t timestamp = 0;
1663
    AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
1664

1665 1666 1667
    if (!s->nb_streams)
        return -1;

1668 1669
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
1670
        MXFStreamContext *sc = av_mallocz(sizeof(*sc));
1671 1672 1673
        if (!sc)
            return AVERROR(ENOMEM);
        st->priv_data = sc;
1674

1675 1676 1677 1678 1679
        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;
        }

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

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1744
        if (!sc->index) {
1745 1746 1747 1748 1749 1750
            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
1751
        }
1752

1753
        sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
1754

1755 1756
        memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15);
        sc->track_essence_element_key[15] = present[sc->index];
1757
        PRINT_KEY(s, "track essence element key", sc->track_essence_element_key);
1758 1759 1760 1761

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

1764
    if (s->oformat == &ff_mxf_d10_muxer) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1765 1766 1767
        mxf->essence_container_count = 1;
    }

1768
    if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
1769 1770
        mxf_gen_umid(s);

1771 1772 1773 1774
    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];
1775 1776 1777 1778
        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);
1779 1780
    }

1781 1782
    if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
        timestamp = ff_iso8601_to_unix_time(t->value);
1783 1784
    if (timestamp)
        mxf->timestamp = mxf_parse_timestamp(timestamp);
1785 1786 1787 1788 1789 1790 1791 1792
    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);
1793
    mxf->timecode_track->index = -1;
1794

1795
    if (!spf)
1796
        spf = ff_mxf_get_samples_per_frame(s, (AVRational){ 1, 25 });
1797

1798
    if (ff_audio_interleave_init(s, spf->samples_per_frame, mxf->time_base) < 0)
1799 1800
        return -1;

1801 1802 1803
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1804 1805 1806 1807 1808 1809
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;
1810
    AVIOContext *pb = s->pb;
1811
    unsigned frame;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1812 1813
    uint32_t time_code;

1814
    frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1815 1816

    // write system metadata pack
1817
    avio_write(pb, system_metadata_pack_key, 16);
1818
    klv_encode_ber4_length(pb, 57);
1819 1820 1821 1822
    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
1823
    avio_wb16(pb, mxf->tc.start + frame); // continuity count
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1824
    if (mxf->essence_container_count > 1)
1825
        avio_write(pb, multiple_desc_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1826 1827
    else {
        MXFStreamContext *sc = s->streams[0]->priv_data;
1828
        avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1829
    }
1830 1831 1832
    avio_w8(pb, 0);
    avio_wb64(pb, 0);
    avio_wb64(pb, 0); // creation date/time stamp
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1833

1834
    avio_w8(pb, 0x81); // SMPTE 12M time code
1835
    time_code = av_timecode_get_smpte_from_framenum(&mxf->tc, frame);
1836 1837 1838
    avio_wb32(pb, time_code);
    avio_wb32(pb, 0); // binary group data
    avio_wb64(pb, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1839 1840

    // write system metadata package set
1841
    avio_write(pb, system_metadata_package_set_key, 16);
1842
    klv_encode_ber4_length(pb, 35);
1843 1844
    avio_w8(pb, 0x83); // UMID
    avio_wb16(pb, 0x20);
1845
    mxf_write_umid(s, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1846 1847
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1848 1849 1850
static void mxf_write_d10_video_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
1851
    AVIOContext *pb = s->pb;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1852 1853 1854 1855 1856 1857 1858 1859
    int packet_size = (uint64_t)st->codec->bit_rate*mxf->time_base.num /
        (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);
1860
    avio_write(pb, pkt->data, pkt->size);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1861 1862 1863 1864

    // ensure CBR muxing by padding to correct video frame size
    pad = packet_size - pkt->size - 16 - 4;
    if (pad > 20) {
1865
        avio_write(s->pb, klv_fill_key, 16);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1866 1867 1868
        pad -= 16 + 4;
        klv_encode_ber4_length(s->pb, pad);
        for (; pad; pad--)
1869
            avio_w8(s->pb, 0);
1870
        av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1)));
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1871 1872 1873
    } else {
        av_log(s, AV_LOG_WARNING, "cannot fill d-10 video packet\n");
        for (; pad > 0; pad--)
1874
            avio_w8(s->pb, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1875 1876 1877 1878 1879 1880
    }
}

static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
    MXFContext *mxf = s->priv_data;
1881
    AVIOContext *pb = s->pb;
1882
    int frame_size = pkt->size / st->codec->block_align;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1883 1884 1885 1886 1887 1888
    uint8_t *samples = pkt->data;
    uint8_t *end = pkt->data + pkt->size;
    int i;

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

1889 1890 1891
    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
1892 1893 1894 1895

    while (samples < end) {
        for (i = 0; i < st->codec->channels; i++) {
            uint32_t sample;
1896
            if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE) {
1897
                sample = AV_RL24(samples)<< 4;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1898 1899
                samples += 3;
            } else {
1900
                sample = AV_RL16(samples)<<12;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1901 1902
                samples += 2;
            }
1903
            avio_wl32(pb, sample | i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1904 1905
        }
        for (; i < 8; i++)
1906
            avio_wl32(pb, i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1907 1908 1909
    }
}

1910
static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
1911
{
1912
    MXFContext *mxf = s->priv_data;
1913
    AVIOContext *pb = s->pb;
1914 1915
    AVStream *st = s->streams[pkt->stream_index];
    MXFStreamContext *sc = st->priv_data;
1916
    MXFIndexEntry ie = {0};
1917

1918
    if (!mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) {
1919
        mxf->index_entries = av_realloc(mxf->index_entries,
1920
            (mxf->edit_units_count + EDIT_UNITS_PER_BODY)*sizeof(*mxf->index_entries));
1921 1922 1923 1924 1925 1926
        if (!mxf->index_entries) {
            av_log(s, AV_LOG_ERROR, "could not allocate index entries\n");
            return -1;
        }
    }

1927
    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1928
        if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
1929 1930
            av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
            return -1;
1931
        }
1932
    } else if (st->codec->codec_id == AV_CODEC_ID_DNXHD) {
1933 1934 1935 1936
        if (!mxf_parse_dnxhd_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
            return -1;
        }
1937
    } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) {
1938 1939 1940 1941
        if (!mxf_parse_dv_frame(s, st, pkt)) {
            av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
            return -1;
        }
1942 1943 1944
    }

    if (!mxf->header_written) {
1945 1946 1947 1948 1949 1950 1951
        if (mxf->edit_unit_byte_count) {
            mxf_write_partition(s, 1, 2, header_open_partition_key, 1);
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        } else {
            mxf_write_partition(s, 0, 0, header_open_partition_key, 1);
        }
1952 1953 1954
        mxf->header_written = 1;
    }

1955
    if (st->index == 0) {
1956 1957
        if (!mxf->edit_unit_byte_count &&
            (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) &&
1958
            !(ie.flags & 0x33)) { // I frame, Gop start
1959 1960 1961 1962 1963 1964 1965
            mxf_write_klv_fill(s);
            mxf_write_partition(s, 1, 2, body_partition_key, 0);

            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
        }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
1966
        mxf_write_klv_fill(s);
1967
        mxf_write_system_item(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
1968

1969 1970
        if (!mxf->edit_unit_byte_count) {
            mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
1971 1972
            mxf->index_entries[mxf->edit_units_count].flags = ie.flags;
            mxf->index_entries[mxf->edit_units_count].temporal_ref = ie.temporal_ref;
1973 1974
            mxf->body_offset += KAG_SIZE; // size of system element
        }
1975
        mxf->edit_units_count++;
1976
    } else if (!mxf->edit_unit_byte_count && st->index == 1) {
1977 1978
        mxf->index_entries[mxf->edit_units_count-1].slice_offset =
            mxf->body_offset - mxf->index_entries[mxf->edit_units_count-1].offset;
1979 1980
    }

1981
    mxf_write_klv_fill(s);
1982
    avio_write(pb, sc->track_essence_element_key, 16); // write key
1983
    if (s->oformat == &ff_mxf_d10_muxer) {
1984
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
1985 1986 1987 1988 1989
            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
1990
        avio_write(pb, pkt->data, pkt->size);
1991 1992
        mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size);
    }
1993

1994
    avio_flush(pb);
1995

1996 1997 1998
    return 0;
}

1999 2000 2001
static void mxf_write_random_index_pack(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
2002
    AVIOContext *pb = s->pb;
2003
    uint64_t pos = avio_tell(pb);
2004
    int i;
2005

2006
    avio_write(pb, random_index_pack_key, 16);
2007
    klv_encode_ber_length(pb, 28 + 12*mxf->body_partitions_count);
2008

2009
    if (mxf->edit_unit_byte_count)
2010
        avio_wb32(pb, 1); // BodySID of header partition
2011
    else
2012 2013
        avio_wb32(pb, 0);
    avio_wb64(pb, 0); // offset of header partition
2014

2015
    for (i = 0; i < mxf->body_partitions_count; i++) {
2016 2017
        avio_wb32(pb, 1); // BodySID
        avio_wb64(pb, mxf->body_partition_offset[i]);
2018 2019
    }

2020 2021
    avio_wb32(pb, 0); // BodySID of footer partition
    avio_wb64(pb, mxf->footer_partition_offset);
2022

2023
    avio_wb32(pb, avio_tell(pb) - pos + 4);
2024 2025
}

2026
static int mxf_write_footer(AVFormatContext *s)
2027
{
2028
    MXFContext *mxf = s->priv_data;
2029
    AVIOContext *pb = s->pb;
2030

2031 2032
    mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;

2033
    mxf_write_klv_fill(s);
2034
    mxf->footer_partition_offset = avio_tell(pb);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2035 2036 2037
    if (mxf->edit_unit_byte_count) { // no need to repeat index
        mxf_write_partition(s, 0, 0, footer_partition_key, 0);
    } else {
2038
        mxf_write_partition(s, 0, 2, footer_partition_key, 0);
2039

2040 2041
        mxf_write_klv_fill(s);
        mxf_write_index_table_segment(s);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2042
    }
2043

2044
    mxf_write_klv_fill(s);
2045 2046
    mxf_write_random_index_pack(s);

2047
    if (s->pb->seekable) {
2048
        avio_seek(pb, 0, SEEK_SET);
2049
        if (mxf->edit_unit_byte_count) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2050 2051 2052
            mxf_write_partition(s, 1, 2, header_closed_partition_key, 1);
            mxf_write_klv_fill(s);
            mxf_write_index_table_segment(s);
2053 2054
        } else {
            mxf_write_partition(s, 0, 0, header_closed_partition_key, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2055
        }
2056
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2057 2058 2059

    ff_audio_interleave_close(s);

Baptiste Coudurier's avatar
Baptiste Coudurier committed
2060
    av_freep(&mxf->index_entries);
2061
    av_freep(&mxf->body_partition_offset);
2062 2063
    av_freep(&mxf->timecode_track->priv_data);
    av_freep(&mxf->timecode_track);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2064

2065
    mxf_free(s);
2066

2067 2068
    return 0;
}
2069

2070
static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
2071
{
2072 2073 2074 2075
    int i, stream_count = 0;

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

    if (stream_count && (s->nb_streams == stream_count || flush)) {
2078
        AVPacketList *pktl = s->packet_buffer;
2079
        if (s->nb_streams != stream_count) {
2080
            AVPacketList *last = NULL;
2081
            // find last packet in edit unit
2082
            while (pktl) {
2083
                if (!stream_count || pktl->pkt.stream_index == 0)
2084
                    break;
2085
                last = pktl;
2086
                pktl = pktl->next;
2087
                stream_count--;
2088
            }
2089 2090 2091
            // purge packet queue
            while (pktl) {
                AVPacketList *next = pktl->next;
2092 2093 2094

                if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
                    s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
2095 2096 2097 2098
                av_free_packet(&pktl->pkt);
                av_freep(&pktl);
                pktl = next;
            }
2099 2100 2101 2102
            if (last)
                last->next = NULL;
            else {
                s->packet_buffer = NULL;
2103
                s->packet_buffer_end= NULL;
2104
                goto out;
2105 2106
            }
            pktl = s->packet_buffer;
2107 2108
        }

2109
        *out = pktl->pkt;
2110
        av_dlog(s, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts);
2111
        s->packet_buffer = pktl->next;
2112 2113 2114 2115
        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;
2116
        av_freep(&pktl);
2117 2118
        return 1;
    } else {
2119
    out:
2120 2121 2122 2123 2124 2125 2126
        av_init_packet(out);
        return 0;
    }
}

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

2130 2131
    return next->dts > pkt->dts ||
        (next->dts == pkt->dts && sc->order < sc2->order);
2132 2133 2134 2135
}

static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
{
2136
    return ff_audio_rechunk_interleave(s, out, pkt, flush,
2137
                               mxf_interleave_get_packet, mxf_compare_timestamps);
2138 2139
}

2140
AVOutputFormat ff_mxf_muxer = {
2141
    .name              = "mxf",
2142
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
2143 2144 2145
    .mime_type         = "application/mxf",
    .extensions        = "mxf",
    .priv_data_size    = sizeof(MXFContext),
2146 2147
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2148 2149 2150 2151 2152
    .write_header      = mxf_write_header,
    .write_packet      = mxf_write_packet,
    .write_trailer     = mxf_write_footer,
    .flags             = AVFMT_NOTIMESTAMPS,
    .interleave_packet = mxf_interleave,
2153
};
Baptiste Coudurier's avatar
Baptiste Coudurier committed
2154

2155
AVOutputFormat ff_mxf_d10_muxer = {
2156
    .name              = "mxf_d10",
2157
    .long_name         = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"),
2158 2159
    .mime_type         = "application/mxf",
    .priv_data_size    = sizeof(MXFContext),
2160 2161
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_MPEG2VIDEO,
2162 2163 2164 2165 2166
    .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
2167
};