Ok-ed parts from patch by zhentan feng.
[ffmpeg.git] / libavformat / mxfenc.c
1 /*
2  * MXF muxer
3  * Copyright (c) 2008 GUCAS, Zhentan Feng <spyfeng at gmail dot com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /*
23  * References
24  * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value
25  * SMPTE 377M MXF File Format Specifications
26  * SMPTE 379M MXF Generic Container
27  * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container
28  * SMPTE RP210: SMPTE Metadata Dictionary
29  * SMPTE RP224: Registry of SMPTE Universal Labels
30  */
31
32 //#define DEBUG
33
34 #include "mxf.h"
35
36 typedef struct {
37     int local_tag;
38     UID uid;
39 } MXFLocalTagPair;
40
41 typedef struct {
42     UID track_essence_element_key;
43 } MXFStreamContext;
44
45 typedef struct MXFContext {
46     int64_t header_byte_count;
47     int64_t header_byte_count_offset;
48     int64_t header_footer_partition_offset;
49     int essence_container_count;
50 } MXFContext;
51 static const uint8_t uuid_base[]            = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
52 static const uint8_t umid_base[]            = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x0F,0x00,0x13,0x00,0x00,0x00 };
53
54 /**
55  * complete key for operation pattern, partitions, and primer pack
56  */
57 static const uint8_t op1a_ul[]              = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x01,0x01,0x00 };
58 static const uint8_t header_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }; // ClosedComplete
59 static const uint8_t footer_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }; // ClosedComplete
60 static const uint8_t primer_pack_key[]      = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x05,0x01,0x00 };
61
62 static void mxf_write_uuid(ByteIOContext *pb, enum CodecID type, int value)
63 {
64     put_buffer(pb, uuid_base, 12);
65     put_be16(pb, type);
66     put_be16(pb, value);
67 }
68
69 static void mxf_write_umid(ByteIOContext *pb, enum CodecID type, int value)
70 {
71     put_buffer(pb, umid_base, 16);
72     mxf_write_uuid(pb, type, value);
73 }
74 static int klv_encode_ber_length(ByteIOContext *pb, uint64_t len)
75 {
76     // Determine the best BER size
77     int size;
78     if (len < 128) {
79         //short form
80         put_byte(pb, len);
81         return 1;
82     }
83
84     size = (av_log2(len) >> 3) + 1;
85
86     // long form
87     put_byte(pb, 0x80 + size);
88     while(size) {
89         size --;
90         put_byte(pb, len >> 8 * size & 0xff);
91     }
92     return 0;
93 }
94
95 static const MXFCodecUL *mxf_get_essence_container_ul(enum CodecID type)
96 {
97     const MXFCodecUL *uls = ff_mxf_essence_container_uls;
98     while (uls->id != CODEC_ID_NONE) {
99         if (uls->id == type)
100             break;
101         uls++;
102     }
103     return uls;
104 }
105
106 static int mxf_write_primer_pack(AVFormatContext *s)
107 {
108     ByteIOContext *pb = s->pb;
109     int local_tag_number, i = 0;
110
111     local_tag_number = sizeof(mxf_local_tag_batch) / sizeof(MXFLocalTagPair);
112
113     put_buffer(pb, primer_pack_key, 16);
114     klv_encode_ber_length(pb, local_tag_number * 18 + 8);
115
116     put_be32(pb, local_tag_number); // local_tag num
117     put_be32(pb, 18); // item size, always 18 according to the specs
118
119     for (i = 0; i < local_tag_number; i++) {
120         put_be16(pb, mxf_local_tag_batch[i].local_tag);
121         put_buffer(pb, mxf_local_tag_batch[i].uid, 16);
122     }
123     return 0;
124 }
125
126 static void mxf_write_local_tag(ByteIOContext *pb, int value_size, int tag)
127 {
128     put_be16(pb, tag);
129     put_be16(pb, value_size);
130 }
131
132 static void mxf_write_metadata_key(ByteIOContext *pb, unsigned int value)
133 {
134     put_buffer(pb, header_metadata_key, 13);
135     put_be24(pb, value);
136 }
137
138 static void mxf_free(AVFormatContext *s)
139 {
140     AVStream *st;
141     int i;
142
143     for (i = 0; i < s->nb_streams; i++) {
144         st = s->streams[i];
145         av_freep(&st->priv_data);
146     }
147 }
148
149 static const MXFDataDefinitionUL *mxf_get_data_definition_ul(enum CodecType type)
150 {
151     const MXFDataDefinitionUL *uls = ff_mxf_data_definition_uls;
152     while (uls->type != CODEC_TYPE_DATA) {
153         if (type == uls->type)
154             break;
155         uls ++;
156     }
157     return uls;
158 }
159
160 static int mux_write_packet(AVFormatContext *s, AVPacket *pkt)
161 {
162     ByteIOContext *pb = s->pb;
163     AVStream *st = s->streams[pkt->stream_index];
164     MXFStreamContext *sc = st->priv_data;
165
166     put_buffer(pb, sc->track_essence_element_key, 16); // write key
167     klv_encode_ber_length(pb, pkt->size); // write length
168     put_buffer(pb, pkt->data, pkt->size); // write value
169
170     put_flush_packet(pb);
171     return 0;
172 }
173
174 static int mxf_write_header_metadata_sets(AVFormatContext *s)
175 {
176     AVStream *st;
177     MXFStreamContext *sc = NULL;
178     int i;
179     if (mxf_write_preface(s) < 0)
180         return -1;
181
182     if (mxf_write_identification(s) < 0)
183         return -1;
184
185     if (mxf_write_content_storage(s) < 0)
186         return -1;
187
188     for (i = 0; i < s->nb_streams; i++) {
189         st = s->streams[i];
190         sc = av_mallocz(sizeof(MXFStreamContext));
191         if (!sc)
192             return AVERROR(ENOMEM);
193         st->priv_data = sc;
194         // set pts information
195         if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
196             av_set_pts_info(st, 64, 1, st->codec->time_base.den);
197         } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
198             av_set_pts_info(st, 64, 1, st->codec->sample_rate);
199         }
200     }
201
202     if (mxf_build_structural_metadata(s, MaterialPackage) < 0)
203         return -1;
204
205     if (mxf_build_structural_metadata(s, SourcePackage) < 0)
206         return -1;
207     return 0;
208 }
209
210 static int mxf_update_header_partition(AVFormatContext *s, int64_t footer_partition_offset)
211 {
212     MXFContext *mxf = s->priv_data;
213     ByteIOContext *pb = s->pb;
214
215     url_fseek(pb, mxf->header_byte_count_offset, SEEK_SET);
216     put_be64(pb, mxf->header_byte_count);
217     put_flush_packet(pb);
218
219     url_fseek(pb, mxf->header_footer_partition_offset, SEEK_SET);
220     put_be64(pb, footer_partition_offset);
221     put_flush_packet(pb);
222     return 0;
223 }
224 AVOutputFormat mxf_muxer = {
225     "mxf",
226     NULL_IF_CONFIG_SMALL("Material eXchange Format"),
227     NULL,
228     "mxf",
229     sizeof(MXFContext),
230     CODEC_ID_PCM_S16LE,
231     CODEC_ID_MPEG2VIDEO,
232     mux_write_header,
233     mux_write_packet,
234     mux_write_footer,
235 };