Mercurial > libavformat.hg
annotate gxfenc.c @ 6118:6780dc315f36 libavformat
Remove support for pre-Haiku, non-POSIX, non-C99 BeOS variants.
BeOS support has been broken for many years and the "maintainer" of the port
has not reacted to countless requests to get the port fixed.
approved by Mans
author | diego |
---|---|
date | Thu, 10 Jun 2010 16:51:14 +0000 |
parents | 536e5527c1e0 |
children | e8dfc68ad182 |
rev | line source |
---|---|
1183 | 1 /* |
2 * GXF muxer. | |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4098
diff
changeset
|
3 * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com> |
1183 | 4 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1322
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1322
diff
changeset
|
6 * |
2252
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
8 * modify it under the terms of the GNU Lesser General Public |
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
9 * License as published by the Free Software Foundation; either |
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
1183 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1322
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
1183 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2252
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
15 * Lesser General Public License for more details. |
1183 | 16 * |
2252
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
17 * You should have received a copy of the GNU Lesser General Public |
708e6e93d6f2
Smartjog granted permission to relicense as LGPL 2.1
bcoudurier
parents:
2251
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1322
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
1183 | 20 */ |
21 | |
22 #include "avformat.h" | |
23 #include "gxf.h" | |
24 #include "riff.h" | |
4401 | 25 #include "audiointerleave.h" |
1183 | 26 |
27 #define GXF_AUDIO_PACKET_SIZE 65536 | |
28 | |
29 typedef struct GXFStreamContext { | |
4401 | 30 AudioInterleaveContext aic; |
1183 | 31 uint32_t track_type; |
32 uint32_t sample_size; | |
33 uint32_t sample_rate; | |
34 uint16_t media_type; | |
35 uint16_t media_info; | |
36 int frame_rate_index; | |
37 int lines_index; | |
38 int fields; | |
39 int iframes; | |
40 int pframes; | |
41 int bframes; | |
42 int p_per_gop; | |
4456
833d30447d64
rename wrongly named b_per_gop to b_per_i_or_p according to specs
bcoudurier
parents:
4426
diff
changeset
|
43 int b_per_i_or_p; ///< number of B frames per I frame or P frame |
1261 | 44 int first_gop_closed; |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
45 unsigned order; ///< interleaving order |
1183 | 46 } GXFStreamContext; |
47 | |
48 typedef struct GXFContext { | |
4479 | 49 uint32_t nb_fields; |
1183 | 50 uint16_t audio_tracks; |
51 uint16_t mpeg_tracks; | |
52 int64_t creation_time; | |
53 uint32_t umf_start_offset; | |
54 uint32_t umf_track_offset; | |
55 uint32_t umf_media_offset; | |
56 uint32_t umf_length; | |
57 uint16_t umf_track_size; | |
58 uint16_t umf_media_size; | |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
59 AVRational time_base; |
1183 | 60 int flags; |
4676 | 61 GXFStreamContext timecode_track; |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
62 unsigned *flt_entries; ///< offsets of packets /1024, starts after 2nd video field |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
63 unsigned flt_entries_nb; |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
64 uint64_t *map_offsets; ///< offset of map packets |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
65 unsigned map_offsets_nb; |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
66 unsigned packet_count; |
1183 | 67 } GXFContext; |
68 | |
4680 | 69 static const struct { |
70 int height, index; | |
71 } gxf_lines_tab[] = { | |
1183 | 72 { 480, 1 }, /* NTSC */ |
73 { 512, 1 }, /* NTSC + VBI */ | |
74 { 576, 2 }, /* PAL */ | |
75 { 608, 2 }, /* PAL + VBI */ | |
76 { 1080, 4 }, | |
77 { 720, 6 }, | |
78 }; | |
79 | |
1677
2a85c82b8538
add codec_id <-> codec_tag tables to AVIn/OutputFormat
michael
parents:
1542
diff
changeset
|
80 static const AVCodecTag gxf_media_types[] = { |
1183 | 81 { CODEC_ID_MJPEG , 3 }, /* NTSC */ |
82 { CODEC_ID_MJPEG , 4 }, /* PAL */ | |
83 { CODEC_ID_PCM_S24LE , 9 }, | |
84 { CODEC_ID_PCM_S16LE , 10 }, | |
85 { CODEC_ID_MPEG2VIDEO, 11 }, /* NTSC */ | |
86 { CODEC_ID_MPEG2VIDEO, 12 }, /* PAL */ | |
87 { CODEC_ID_DVVIDEO , 13 }, /* NTSC */ | |
88 { CODEC_ID_DVVIDEO , 14 }, /* PAL */ | |
89 { CODEC_ID_DVVIDEO , 15 }, /* 50M NTSC */ | |
90 { CODEC_ID_DVVIDEO , 16 }, /* 50M PAL */ | |
91 { CODEC_ID_AC3 , 17 }, | |
92 //{ CODEC_ID_NONE, , 18 }, /* Non compressed 24 bit audio */ | |
93 { CODEC_ID_MPEG2VIDEO, 20 }, /* MPEG HD */ | |
94 { CODEC_ID_MPEG1VIDEO, 22 }, /* NTSC */ | |
95 { CODEC_ID_MPEG1VIDEO, 23 }, /* PAL */ | |
5290
0d5653941bf9
Make AVCodecTag.id enum CodecID and use CODEC_ID_NONE instead of 0.
cehoyos
parents:
5058
diff
changeset
|
96 { CODEC_ID_NONE, 0 }, |
1183 | 97 }; |
98 | |
4681
83c634df5c79
change path pattern to be similar to existing files, and remove useless buffer
bcoudurier
parents:
4680
diff
changeset
|
99 #define SERVER_PATH "EXT:/PDR/default/" |
83c634df5c79
change path pattern to be similar to existing files, and remove useless buffer
bcoudurier
parents:
4680
diff
changeset
|
100 #define ES_NAME_PATTERN "EXT:/PDR/default/ES." |
1183 | 101 |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
102 static int gxf_find_lines_index(AVStream *st) |
1183 | 103 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
104 GXFStreamContext *sc = st->priv_data; |
1183 | 105 int i; |
106 | |
107 for (i = 0; i < 6; ++i) { | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
108 if (st->codec->height == gxf_lines_tab[i].height) { |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
109 sc->lines_index = gxf_lines_tab[i].index; |
1183 | 110 return 0; |
111 } | |
112 } | |
113 return -1; | |
114 } | |
115 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
116 static void gxf_write_padding(ByteIOContext *pb, int64_t to_pad) |
1183 | 117 { |
1213 | 118 for (; to_pad > 0; to_pad--) { |
1183 | 119 put_byte(pb, 0); |
120 } | |
121 } | |
122 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
123 static int64_t updatePacketSize(ByteIOContext *pb, int64_t pos) |
1183 | 124 { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
125 int64_t curpos; |
1183 | 126 int size; |
127 | |
128 size = url_ftell(pb) - pos; | |
129 if (size % 4) { | |
130 gxf_write_padding(pb, 4 - size % 4); | |
131 size = url_ftell(pb) - pos; | |
132 } | |
133 curpos = url_ftell(pb); | |
134 url_fseek(pb, pos + 6, SEEK_SET); | |
135 put_be32(pb, size); | |
136 url_fseek(pb, curpos, SEEK_SET); | |
137 return curpos - pos; | |
138 } | |
139 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
140 static int64_t updateSize(ByteIOContext *pb, int64_t pos) |
1183 | 141 { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
142 int64_t curpos; |
1183 | 143 |
144 curpos = url_ftell(pb); | |
145 url_fseek(pb, pos, SEEK_SET); | |
146 put_be16(pb, curpos - pos - 2); | |
147 url_fseek(pb, curpos, SEEK_SET); | |
148 return curpos - pos; | |
149 } | |
150 | |
4098 | 151 static void gxf_write_packet_header(ByteIOContext *pb, GXFPktType type) |
1183 | 152 { |
153 put_be32(pb, 0); /* packet leader for synchro */ | |
154 put_byte(pb, 1); | |
155 put_byte(pb, type); /* map packet */ | |
156 put_be32(pb, 0); /* size */ | |
157 put_be32(pb, 0); /* reserved */ | |
158 put_byte(pb, 0xE1); /* trailer 1 */ | |
159 put_byte(pb, 0xE2); /* trailer 2 */ | |
160 } | |
161 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
162 static int gxf_write_mpeg_auxiliary(ByteIOContext *pb, AVStream *st) |
1183 | 163 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
164 GXFStreamContext *sc = st->priv_data; |
1183 | 165 char buffer[1024]; |
4261 | 166 int size, starting_line; |
1183 | 167 |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
168 if (sc->iframes) { |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
169 sc->p_per_gop = sc->pframes / sc->iframes; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
170 if (sc->pframes % sc->iframes) |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
171 sc->p_per_gop++; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
172 if (sc->pframes) { |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
173 sc->b_per_i_or_p = sc->bframes / sc->pframes; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
174 if (sc->bframes % sc->pframes) |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
175 sc->b_per_i_or_p++; |
4457
6ed62b8257dd
compute b_per_i_or_p value correctly, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4456
diff
changeset
|
176 } |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
177 if (sc->p_per_gop > 9) |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
178 sc->p_per_gop = 9; /* ensure value won't take more than one char */ |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
179 if (sc->b_per_i_or_p > 9) |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
180 sc->b_per_i_or_p = 9; /* ensure value won't take more than one char */ |
1183 | 181 } |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
182 if (st->codec->height == 512 || st->codec->height == 608) |
4261 | 183 starting_line = 7; // VBI |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
184 else if (st->codec->height == 480) |
4261 | 185 starting_line = 20; |
186 else | |
187 starting_line = 23; // default PAL | |
188 | |
1183 | 189 size = snprintf(buffer, 1024, "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n" |
4261 | 190 "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n", |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
191 (float)st->codec->bit_rate, sc->p_per_gop, sc->b_per_i_or_p, |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
192 st->codec->pix_fmt == PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1, |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
193 starting_line, st->codec->height / 16); |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
194 put_byte(pb, TRACK_MPG_AUX); |
1183 | 195 put_byte(pb, size + 1); |
196 put_buffer(pb, (uint8_t *)buffer, size + 1); | |
197 return size + 3; | |
198 } | |
199 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
200 static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *sc) |
1183 | 201 { |
202 put_byte(pb, 0); /* fields */ | |
203 put_byte(pb, 0); /* seconds */ | |
204 put_byte(pb, 0); /* minutes */ | |
205 put_byte(pb, 0); /* flags + hours */ | |
206 /* reserved */ | |
207 put_be32(pb, 0); | |
208 return 8; | |
209 } | |
210 | |
4676 | 211 static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, int index) |
1183 | 212 { |
4676 | 213 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
214 int64_t pos; |
4676 | 215 int mpeg = sc->track_type == 4 || sc->track_type == 9; |
1183 | 216 |
217 /* track description section */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
218 put_byte(pb, sc->media_type + 0x80); |
4676 | 219 put_byte(pb, index + 0xC0); |
1183 | 220 |
221 pos = url_ftell(pb); | |
222 put_be16(pb, 0); /* size */ | |
223 | |
224 /* media file name */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
225 put_byte(pb, TRACK_NAME); |
1183 | 226 put_byte(pb, strlen(ES_NAME_PATTERN) + 3); |
227 put_tag(pb, ES_NAME_PATTERN); | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
228 put_be16(pb, sc->media_info); |
1183 | 229 put_byte(pb, 0); |
230 | |
4676 | 231 if (!mpeg) { |
1183 | 232 /* auxiliary information */ |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
233 put_byte(pb, TRACK_AUX); |
1183 | 234 put_byte(pb, 8); |
4676 | 235 if (sc->track_type == 3) |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
236 gxf_write_timecode_auxiliary(pb, sc); |
1183 | 237 else |
238 put_le64(pb, 0); | |
239 } | |
240 | |
241 /* file system version */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
242 put_byte(pb, TRACK_VER); |
1183 | 243 put_byte(pb, 4); |
244 put_be32(pb, 0); | |
245 | |
4676 | 246 if (mpeg) |
247 gxf_write_mpeg_auxiliary(pb, s->streams[index]); | |
1183 | 248 |
249 /* frame rate */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
250 put_byte(pb, TRACK_FPS); |
1183 | 251 put_byte(pb, 4); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
252 put_be32(pb, sc->frame_rate_index); |
1183 | 253 |
254 /* lines per frame */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
255 put_byte(pb, TRACK_LINES); |
1183 | 256 put_byte(pb, 4); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
257 put_be32(pb, sc->lines_index); |
1183 | 258 |
259 /* fields per frame */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
260 put_byte(pb, TRACK_FPF); |
1183 | 261 put_byte(pb, 4); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
262 put_be32(pb, sc->fields); |
1183 | 263 |
264 return updateSize(pb, pos); | |
265 } | |
266 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
267 static int gxf_write_material_data_section(AVFormatContext *s) |
1183 | 268 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
269 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
270 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
271 int64_t pos; |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
272 const char *filename = strrchr(s->filename, '/'); |
1183 | 273 |
274 pos = url_ftell(pb); | |
275 put_be16(pb, 0); /* size */ | |
276 | |
277 /* name */ | |
278 if (filename) | |
279 filename++; | |
280 else | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
281 filename = s->filename; |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
282 put_byte(pb, MAT_NAME); |
1183 | 283 put_byte(pb, strlen(SERVER_PATH) + strlen(filename) + 1); |
284 put_tag(pb, SERVER_PATH); | |
285 put_tag(pb, filename); | |
286 put_byte(pb, 0); | |
287 | |
288 /* first field */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
289 put_byte(pb, MAT_FIRST_FIELD); |
1183 | 290 put_byte(pb, 4); |
291 put_be32(pb, 0); | |
292 | |
293 /* last field */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
294 put_byte(pb, MAT_LAST_FIELD); |
1183 | 295 put_byte(pb, 4); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
296 put_be32(pb, gxf->nb_fields); |
1183 | 297 |
298 /* reserved */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
299 put_byte(pb, MAT_MARK_IN); |
1183 | 300 put_byte(pb, 4); |
301 put_be32(pb, 0); | |
302 | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
303 put_byte(pb, MAT_MARK_OUT); |
1183 | 304 put_byte(pb, 4); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
305 put_be32(pb, gxf->nb_fields); |
1183 | 306 |
307 /* estimated size */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
308 put_byte(pb, MAT_SIZE); |
1183 | 309 put_byte(pb, 4); |
310 put_be32(pb, url_fsize(pb) / 1024); | |
311 | |
312 return updateSize(pb, pos); | |
313 } | |
314 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
315 static int gxf_write_track_description_section(AVFormatContext *s) |
1183 | 316 { |
4676 | 317 GXFContext *gxf = s->priv_data; |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
318 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
319 int64_t pos; |
1183 | 320 int i; |
321 | |
322 pos = url_ftell(pb); | |
323 put_be16(pb, 0); /* size */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
324 for (i = 0; i < s->nb_streams; ++i) |
4676 | 325 gxf_write_track_description(s, s->streams[i]->priv_data, i); |
326 | |
327 gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams); | |
328 | |
1183 | 329 return updateSize(pb, pos); |
330 } | |
331 | |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
332 static int gxf_write_map_packet(AVFormatContext *s, int rewrite) |
1183 | 333 { |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
334 GXFContext *gxf = s->priv_data; |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
335 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
336 int64_t pos = url_ftell(pb); |
1183 | 337 |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
338 if (!rewrite) { |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
339 if (!(gxf->map_offsets_nb % 30)) { |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
340 gxf->map_offsets = av_realloc(gxf->map_offsets, |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
341 (gxf->map_offsets_nb+30)*sizeof(*gxf->map_offsets)); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
342 if (!gxf->map_offsets) { |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
343 av_log(s, AV_LOG_ERROR, "could not realloc map offsets\n"); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
344 return -1; |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
345 } |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
346 } |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
347 gxf->map_offsets[gxf->map_offsets_nb++] = pos; // do not increment here |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
348 } |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
349 |
1183 | 350 gxf_write_packet_header(pb, PKT_MAP); |
351 | |
352 /* preamble */ | |
353 put_byte(pb, 0xE0); /* version */ | |
354 put_byte(pb, 0xFF); /* reserved */ | |
355 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
356 gxf_write_material_data_section(s); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
357 gxf_write_track_description_section(s); |
1183 | 358 |
359 return updatePacketSize(pb, pos); | |
360 } | |
361 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
362 static int gxf_write_flt_packet(AVFormatContext *s) |
1183 | 363 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
364 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
365 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
366 int64_t pos = url_ftell(pb); |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
367 int fields_per_flt = (gxf->nb_fields+1) / 1000 + 1; |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
368 int flt_entries = gxf->nb_fields / fields_per_flt - 1; |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
369 int i = 0; |
1183 | 370 |
371 gxf_write_packet_header(pb, PKT_FLT); | |
372 | |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
373 put_le32(pb, fields_per_flt); /* number of fields */ |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
374 put_le32(pb, flt_entries); /* number of active flt entries */ |
1183 | 375 |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
376 if (gxf->flt_entries) { |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
377 for (i = 0; i < flt_entries; i++) |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
378 put_le32(pb, gxf->flt_entries[(i*fields_per_flt)>>1]); |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
379 } |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
380 |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
381 for (; i < 1000; i++) |
1183 | 382 put_le32(pb, 0); |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
383 |
1183 | 384 return updatePacketSize(pb, pos); |
385 } | |
386 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
387 static int gxf_write_umf_material_description(AVFormatContext *s) |
1183 | 388 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
389 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
390 ByteIOContext *pb = s->pb; |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
391 int timecode_base = gxf->time_base.den == 60000 ? 60 : 50; |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
392 |
4260 | 393 // XXX drop frame |
394 uint32_t timecode = | |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
395 gxf->nb_fields / (timecode_base * 3600) % 24 << 24 | // hours |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
396 gxf->nb_fields / (timecode_base * 60) % 60 << 16 | // minutes |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
397 gxf->nb_fields / timecode_base % 60 << 8 | // seconds |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
398 gxf->nb_fields % timecode_base; // fields |
4260 | 399 |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
400 put_le32(pb, gxf->flags); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
401 put_le32(pb, gxf->nb_fields); /* length of the longest track */ |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
402 put_le32(pb, gxf->nb_fields); /* length of the shortest track */ |
1183 | 403 put_le32(pb, 0); /* mark in */ |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
404 put_le32(pb, gxf->nb_fields); /* mark out */ |
1183 | 405 put_le32(pb, 0); /* timecode mark in */ |
4260 | 406 put_le32(pb, timecode); /* timecode mark out */ |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
407 put_le64(pb, s->timestamp); /* modification time */ |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
408 put_le64(pb, s->timestamp); /* creation time */ |
1183 | 409 put_le16(pb, 0); /* reserved */ |
410 put_le16(pb, 0); /* reserved */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
411 put_le16(pb, gxf->audio_tracks); |
4676 | 412 put_le16(pb, 1); /* timecode track count */ |
1183 | 413 put_le16(pb, 0); /* reserved */ |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
414 put_le16(pb, gxf->mpeg_tracks); |
1183 | 415 return 48; |
416 } | |
417 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
418 static int gxf_write_umf_payload(AVFormatContext *s) |
1183 | 419 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
420 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
421 ByteIOContext *pb = s->pb; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
422 |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
423 put_le32(pb, gxf->umf_length); /* total length of the umf data */ |
1183 | 424 put_le32(pb, 3); /* version */ |
4676 | 425 put_le32(pb, s->nb_streams+1); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
426 put_le32(pb, gxf->umf_track_offset); /* umf track section offset */ |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
427 put_le32(pb, gxf->umf_track_size); |
4676 | 428 put_le32(pb, s->nb_streams+1); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
429 put_le32(pb, gxf->umf_media_offset); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
430 put_le32(pb, gxf->umf_media_size); |
4673 | 431 put_le32(pb, gxf->umf_length); /* user data offset */ |
432 put_le32(pb, 0); /* user data size */ | |
1183 | 433 put_le32(pb, 0); /* reserved */ |
434 put_le32(pb, 0); /* reserved */ | |
435 return 48; | |
436 } | |
437 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
438 static int gxf_write_umf_track_description(AVFormatContext *s) |
1183 | 439 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
440 ByteIOContext *pb = s->pb; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
441 GXFContext *gxf = s->priv_data; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
442 int64_t pos = url_ftell(pb); |
1183 | 443 int i; |
444 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
445 gxf->umf_track_offset = pos - gxf->umf_start_offset; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
446 for (i = 0; i < s->nb_streams; ++i) { |
4675 | 447 GXFStreamContext *sc = s->streams[i]->priv_data; |
1183 | 448 put_le16(pb, sc->media_info); |
449 put_le16(pb, 1); | |
450 } | |
4676 | 451 |
452 put_le16(pb, gxf->timecode_track.media_info); | |
453 put_le16(pb, 1); | |
454 | |
1183 | 455 return url_ftell(pb) - pos; |
456 } | |
457 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
458 static int gxf_write_umf_media_mpeg(ByteIOContext *pb, AVStream *st) |
1183 | 459 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
460 GXFStreamContext *sc = st->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
461 |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
462 if (st->codec->pix_fmt == PIX_FMT_YUV422P) |
1183 | 463 put_le32(pb, 2); |
464 else | |
465 put_le32(pb, 1); /* default to 420 */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
466 put_le32(pb, sc->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */ |
1183 | 467 put_le32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */ |
468 put_le32(pb, 1); /* I picture per GOP */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
469 put_le32(pb, sc->p_per_gop); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
470 put_le32(pb, sc->b_per_i_or_p); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
471 if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) |
1183 | 472 put_le32(pb, 2); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
473 else if (st->codec->codec_id == CODEC_ID_MPEG1VIDEO) |
1183 | 474 put_le32(pb, 1); |
475 else | |
476 put_le32(pb, 0); | |
477 put_le32(pb, 0); /* reserved */ | |
478 return 32; | |
479 } | |
480 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
481 static int gxf_write_umf_media_timecode(ByteIOContext *pb, GXFStreamContext *sc) |
1183 | 482 { |
4676 | 483 put_le32(pb, 1); /* non drop frame */ |
484 put_le32(pb, 0); /* reserved */ | |
485 put_le32(pb, 0); /* reserved */ | |
486 put_le32(pb, 0); /* reserved */ | |
487 put_le32(pb, 0); /* reserved */ | |
488 put_le32(pb, 0); /* reserved */ | |
489 put_le32(pb, 0); /* reserved */ | |
490 put_le32(pb, 0); /* reserved */ | |
1183 | 491 return 32; |
492 } | |
493 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
494 static int gxf_write_umf_media_dv(ByteIOContext *pb, GXFStreamContext *sc) |
1183 | 495 { |
496 int i; | |
497 | |
498 for (i = 0; i < 8; i++) { | |
499 put_be32(pb, 0); | |
500 } | |
501 return 32; | |
502 } | |
503 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
504 static int gxf_write_umf_media_audio(ByteIOContext *pb, GXFStreamContext *sc) |
1183 | 505 { |
506 put_le64(pb, av_dbl2int(1)); /* sound level to begin to */ | |
507 put_le64(pb, av_dbl2int(1)); /* sound level to begin to */ | |
508 put_le32(pb, 0); /* number of fields over which to ramp up sound level */ | |
509 put_le32(pb, 0); /* number of fields over which to ramp down sound level */ | |
510 put_le32(pb, 0); /* reserved */ | |
511 put_le32(pb, 0); /* reserved */ | |
512 return 32; | |
513 } | |
514 | |
515 #if 0 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
516 static int gxf_write_umf_media_mjpeg(ByteIOContext *pb, GXFStreamContext *sc) |
1183 | 517 { |
518 put_be64(pb, 0); /* FIXME FLOAT max chroma quant level */ | |
519 put_be64(pb, 0); /* FIXME FLOAT max luma quant level */ | |
520 put_be64(pb, 0); /* FIXME FLOAT min chroma quant level */ | |
521 put_be64(pb, 0); /* FIXME FLOAT min luma quant level */ | |
522 return 32; | |
523 } | |
524 #endif | |
525 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
526 static int gxf_write_umf_media_description(AVFormatContext *s) |
1183 | 527 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
528 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
529 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
530 int64_t pos; |
4681
83c634df5c79
change path pattern to be similar to existing files, and remove useless buffer
bcoudurier
parents:
4680
diff
changeset
|
531 int i, j; |
1183 | 532 |
533 pos = url_ftell(pb); | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
534 gxf->umf_media_offset = pos - gxf->umf_start_offset; |
4676 | 535 for (i = 0; i <= s->nb_streams; ++i) { |
536 GXFStreamContext *sc; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
537 int64_t startpos, curpos; |
1183 | 538 |
4676 | 539 if (i == s->nb_streams) |
540 sc = &gxf->timecode_track; | |
541 else | |
542 sc = s->streams[i]->priv_data; | |
543 | |
1183 | 544 startpos = url_ftell(pb); |
545 put_le16(pb, 0); /* length */ | |
546 put_le16(pb, sc->media_info); | |
547 put_le16(pb, 0); /* reserved */ | |
548 put_le16(pb, 0); /* reserved */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
549 put_le32(pb, gxf->nb_fields); |
1183 | 550 put_le32(pb, 0); /* attributes rw, ro */ |
551 put_le32(pb, 0); /* mark in */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
552 put_le32(pb, gxf->nb_fields); /* mark out */ |
4681
83c634df5c79
change path pattern to be similar to existing files, and remove useless buffer
bcoudurier
parents:
4680
diff
changeset
|
553 put_buffer(pb, ES_NAME_PATTERN, sizeof(ES_NAME_PATTERN)); |
1183 | 554 put_be16(pb, sc->media_info); |
4681
83c634df5c79
change path pattern to be similar to existing files, and remove useless buffer
bcoudurier
parents:
4680
diff
changeset
|
555 for (j = sizeof(ES_NAME_PATTERN)+2; j < 88; j++) |
83c634df5c79
change path pattern to be similar to existing files, and remove useless buffer
bcoudurier
parents:
4680
diff
changeset
|
556 put_byte(pb, 0); |
1183 | 557 put_le32(pb, sc->track_type); |
558 put_le32(pb, sc->sample_rate); | |
559 put_le32(pb, sc->sample_size); | |
560 put_le32(pb, 0); /* reserved */ | |
4676 | 561 |
562 if (sc == &gxf->timecode_track) | |
563 gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */ | |
564 else { | |
565 AVStream *st = s->streams[i]; | |
4682 | 566 switch (st->codec->codec_id) { |
567 case CODEC_ID_MPEG2VIDEO: | |
568 gxf_write_umf_media_mpeg(pb, st); | |
569 break; | |
570 case CODEC_ID_PCM_S16LE: | |
571 gxf_write_umf_media_audio(pb, sc); | |
572 break; | |
573 case CODEC_ID_DVVIDEO: | |
574 gxf_write_umf_media_dv(pb, sc); | |
575 break; | |
576 } | |
1183 | 577 } |
4676 | 578 |
1183 | 579 curpos = url_ftell(pb); |
580 url_fseek(pb, startpos, SEEK_SET); | |
581 put_le16(pb, curpos - startpos); | |
582 url_fseek(pb, curpos, SEEK_SET); | |
583 } | |
584 return url_ftell(pb) - pos; | |
585 } | |
586 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
587 static int gxf_write_umf_packet(AVFormatContext *s) |
1183 | 588 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
589 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
590 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
591 int64_t pos = url_ftell(pb); |
1183 | 592 |
593 gxf_write_packet_header(pb, PKT_UMF); | |
594 | |
595 /* preamble */ | |
596 put_byte(pb, 3); /* first and last (only) packet */ | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
597 put_be32(pb, gxf->umf_length); /* data length */ |
1183 | 598 |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
599 gxf->umf_start_offset = url_ftell(pb); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
600 gxf_write_umf_payload(s); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
601 gxf_write_umf_material_description(s); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
602 gxf->umf_track_size = gxf_write_umf_track_description(s); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
603 gxf->umf_media_size = gxf_write_umf_media_description(s); |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
604 gxf->umf_length = url_ftell(pb) - gxf->umf_start_offset; |
1183 | 605 return updatePacketSize(pb, pos); |
606 } | |
607 | |
4401 | 608 static const int GXF_samples_per_frame[] = { 32768, 0 }; |
609 | |
4676 | 610 static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc) |
611 { | |
612 if (!vsc) | |
613 return; | |
614 | |
615 sc->media_type = vsc->sample_rate == 60 ? 7 : 8; | |
616 sc->sample_rate = vsc->sample_rate; | |
617 sc->media_info = ('T'<<8) | '0'; | |
618 sc->track_type = 3; | |
619 sc->frame_rate_index = vsc->frame_rate_index; | |
620 sc->lines_index = vsc->lines_index; | |
621 sc->sample_size = 16; | |
622 sc->fields = vsc->fields; | |
623 } | |
624 | |
1183 | 625 static int gxf_write_header(AVFormatContext *s) |
626 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2337
diff
changeset
|
627 ByteIOContext *pb = s->pb; |
1183 | 628 GXFContext *gxf = s->priv_data; |
4676 | 629 GXFStreamContext *vsc = NULL; |
4675 | 630 uint8_t tracks[255] = {0}; |
631 int i, media_info = 0; | |
1183 | 632 |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
633 if (url_is_streamed(pb)) { |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
634 av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome"); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
635 return -1; |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
636 } |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
637 |
1183 | 638 gxf->flags |= 0x00080000; /* material is simple clip */ |
639 for (i = 0; i < s->nb_streams; ++i) { | |
640 AVStream *st = s->streams[i]; | |
4329 | 641 GXFStreamContext *sc = av_mallocz(sizeof(*sc)); |
642 if (!sc) | |
643 return AVERROR(ENOMEM); | |
644 st->priv_data = sc; | |
1183 | 645 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4950
diff
changeset
|
646 sc->media_type = ff_codec_get_tag(gxf_media_types, st->codec->codec_id); |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
647 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
1183 | 648 if (st->codec->codec_id != CODEC_ID_PCM_S16LE) { |
649 av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n"); | |
650 return -1; | |
651 } | |
652 if (st->codec->sample_rate != 48000) { | |
653 av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n"); | |
654 return -1; | |
655 } | |
656 if (st->codec->channels != 1) { | |
657 av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n"); | |
658 return -1; | |
659 } | |
660 sc->track_type = 2; | |
661 sc->sample_rate = st->codec->sample_rate; | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
662 av_set_pts_info(st, 64, 1, sc->sample_rate); |
1183 | 663 sc->sample_size = 16; |
664 sc->frame_rate_index = -2; | |
665 sc->lines_index = -2; | |
666 sc->fields = -2; | |
667 gxf->audio_tracks++; | |
668 gxf->flags |= 0x04000000; /* audio is 16 bit pcm */ | |
4675 | 669 media_info = 'A'; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
670 } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
671 if (i != 0) { |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
672 av_log(s, AV_LOG_ERROR, "video stream must be the first track\n"); |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
673 return -1; |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
674 } |
1183 | 675 /* FIXME check from time_base ? */ |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
676 if (st->codec->height == 480 || st->codec->height == 512) { /* NTSC or NTSC+VBI */ |
1183 | 677 sc->frame_rate_index = 5; |
678 sc->sample_rate = 60; | |
679 gxf->flags |= 0x00000080; | |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
680 gxf->time_base = (AVRational){ 1001, 60000 }; |
1183 | 681 } else { /* assume PAL */ |
682 sc->frame_rate_index = 6; | |
683 sc->media_type++; | |
684 sc->sample_rate = 50; | |
685 gxf->flags |= 0x00000040; | |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
686 gxf->time_base = (AVRational){ 1, 50 }; |
1183 | 687 } |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
688 av_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
689 if (gxf_find_lines_index(st) < 0) |
1183 | 690 sc->lines_index = -1; |
691 sc->sample_size = st->codec->bit_rate; | |
692 sc->fields = 2; /* interlaced */ | |
4676 | 693 |
694 vsc = sc; | |
695 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
696 switch (st->codec->codec_id) { |
4675 | 697 case CODEC_ID_MJPEG: |
698 sc->track_type = 1; | |
699 gxf->flags |= 0x00004000; | |
700 media_info = 'J'; | |
701 break; | |
702 case CODEC_ID_MPEG1VIDEO: | |
703 sc->track_type = 9; | |
704 gxf->mpeg_tracks++; | |
705 media_info = 'L'; | |
706 break; | |
1183 | 707 case CODEC_ID_MPEG2VIDEO: |
1262 | 708 sc->first_gop_closed = -1; |
1183 | 709 sc->track_type = 4; |
710 gxf->mpeg_tracks++; | |
711 gxf->flags |= 0x00008000; | |
4675 | 712 media_info = 'M'; |
1183 | 713 break; |
714 case CODEC_ID_DVVIDEO: | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
715 if (st->codec->pix_fmt == PIX_FMT_YUV422P) { |
1183 | 716 sc->media_type += 2; |
717 sc->track_type = 6; | |
718 gxf->flags |= 0x00002000; | |
4675 | 719 media_info = 'E'; |
1183 | 720 } else { |
721 sc->track_type = 5; | |
722 gxf->flags |= 0x00001000; | |
4675 | 723 media_info = 'D'; |
1183 | 724 } |
725 break; | |
726 default: | |
1401 | 727 av_log(s, AV_LOG_ERROR, "video codec not supported\n"); |
1183 | 728 return -1; |
729 } | |
730 } | |
4675 | 731 /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */ |
732 sc->media_info = media_info<<8 | ('0'+tracks[media_info]++); | |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
733 sc->order = s->nb_streams - st->index; |
1183 | 734 } |
4401 | 735 |
736 if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0) | |
737 return -1; | |
738 | |
4676 | 739 gxf_init_timecode_track(&gxf->timecode_track, vsc); |
740 gxf->flags |= 0x200000; // time code track is non-drop frame | |
741 | |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
742 gxf_write_map_packet(s, 0); |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
743 gxf_write_flt_packet(s); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
744 gxf_write_umf_packet(s); |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
745 |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
746 gxf->packet_count = 3; |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
747 |
1183 | 748 put_flush_packet(pb); |
749 return 0; | |
750 } | |
751 | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
752 static int gxf_write_eos_packet(ByteIOContext *pb) |
1183 | 753 { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
754 int64_t pos = url_ftell(pb); |
1183 | 755 |
756 gxf_write_packet_header(pb, PKT_EOS); | |
757 return updatePacketSize(pb, pos); | |
758 } | |
759 | |
760 static int gxf_write_trailer(AVFormatContext *s) | |
761 { | |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
762 GXFContext *gxf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2337
diff
changeset
|
763 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
764 int64_t end; |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
765 int i; |
1183 | 766 |
4401 | 767 ff_audio_interleave_close(s); |
1183 | 768 |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
769 gxf_write_eos_packet(pb); |
1183 | 770 end = url_ftell(pb); |
771 url_fseek(pb, 0, SEEK_SET); | |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
772 /* overwrite map, flt and umf packets with new values */ |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
773 gxf_write_map_packet(s, 1); |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
774 gxf_write_flt_packet(s); |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
775 gxf_write_umf_packet(s); |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
776 put_flush_packet(pb); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
777 /* update duration in all map packets */ |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
778 for (i = 1; i < gxf->map_offsets_nb; i++) { |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
779 url_fseek(pb, gxf->map_offsets[i], SEEK_SET); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
780 gxf_write_map_packet(s, 1); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
781 put_flush_packet(pb); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
782 } |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
783 |
1183 | 784 url_fseek(pb, end, SEEK_SET); |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
785 |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
786 av_freep(&gxf->flt_entries); |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
787 av_freep(&gxf->map_offsets); |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
788 |
1183 | 789 return 0; |
790 } | |
791 | |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
792 static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int size) |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
793 { |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
794 uint32_t c=-1; |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
795 int i; |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
796 for(i=0; i<size-4 && c!=0x100; i++){ |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
797 c = (c<<8) + buf[i]; |
1262 | 798 if(c == 0x1B8 && sc->first_gop_closed == -1) /* GOP start code */ |
1261 | 799 sc->first_gop_closed= (buf[i+4]>>6)&1; |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
800 } |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
801 return (buf[i+1]>>3)&7; |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
802 } |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
803 |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
804 static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size) |
1183 | 805 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
806 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
807 ByteIOContext *pb = s->pb; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
808 AVStream *st = s->streams[pkt->stream_index]; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
809 GXFStreamContext *sc = st->priv_data; |
4480
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
810 unsigned field_nb; |
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
811 /* If the video is frame-encoded, the frame numbers shall be represented by |
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
812 * even field numbers. |
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
813 * see SMPTE360M-2004 6.4.2.1.3 Media field number */ |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
814 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
815 field_nb = gxf->nb_fields; |
4480
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
816 } else { |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
817 field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den, |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
818 (int64_t)48000*gxf->time_base.num, AV_ROUND_UP); |
4480
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
819 } |
1183 | 820 |
821 put_byte(pb, sc->media_type); | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
822 put_byte(pb, st->index); |
4480
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
823 put_be32(pb, field_nb); |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
824 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
1183 | 825 put_be16(pb, 0); |
826 put_be16(pb, size / 2); | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
827 } else if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) { |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
828 int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size); |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
829 if (frame_type == FF_I_TYPE) { |
1183 | 830 put_byte(pb, 0x0d); |
831 sc->iframes++; | |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
832 } else if (frame_type == FF_B_TYPE) { |
1183 | 833 put_byte(pb, 0x0f); |
834 sc->bframes++; | |
835 } else { | |
836 put_byte(pb, 0x0e); | |
837 sc->pframes++; | |
838 } | |
839 put_be24(pb, size); | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
840 } else if (st->codec->codec_id == CODEC_ID_DVVIDEO) { |
1183 | 841 put_byte(pb, size / 4096); |
842 put_be24(pb, 0); | |
843 } else | |
844 put_be32(pb, size); | |
4480
b88326454853
use correct field number for video according to specs, patch by Thierry Foucu, tfoucu at gmail dot com
bcoudurier
parents:
4479
diff
changeset
|
845 put_be32(pb, field_nb); |
1183 | 846 put_byte(pb, 1); /* flags */ |
847 put_byte(pb, 0); /* reserved */ | |
848 return 16; | |
849 } | |
850 | |
4674 | 851 static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt) |
1183 | 852 { |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
853 GXFContext *gxf = s->priv_data; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
854 ByteIOContext *pb = s->pb; |
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
855 AVStream *st = s->streams[pkt->stream_index]; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
856 int64_t pos = url_ftell(pb); |
1183 | 857 int padding = 0; |
858 | |
859 gxf_write_packet_header(pb, PKT_MEDIA); | |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
860 if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */ |
1183 | 861 padding = 4 - pkt->size % 4; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
862 else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) |
1212 | 863 padding = GXF_AUDIO_PACKET_SIZE - pkt->size; |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
864 gxf_write_media_preamble(s, pkt, pkt->size + padding); |
1212 | 865 put_buffer(pb, pkt->data, pkt->size); |
866 gxf_write_padding(pb, padding); | |
4262
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
867 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
868 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
869 if (!(gxf->flt_entries_nb % 500)) { |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
870 gxf->flt_entries = av_realloc(gxf->flt_entries, |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
871 (gxf->flt_entries_nb+500)*sizeof(*gxf->flt_entries)); |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
872 if (!gxf->flt_entries) { |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
873 av_log(s, AV_LOG_ERROR, "could not reallocate flt entries\n"); |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
874 return -1; |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
875 } |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
876 } |
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
877 gxf->flt_entries[gxf->flt_entries_nb++] = url_ftell(pb) / 1024; |
4672
f5d61e72fec5
uniformize variable names and remove duplicating fields in private structs
bcoudurier
parents:
4671
diff
changeset
|
878 gxf->nb_fields += 2; // count fields |
4678
65036104b950
write flt packet, might need some tweaking but it works
bcoudurier
parents:
4677
diff
changeset
|
879 } |
4262
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
880 |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
881 updatePacketSize(pb, pos); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
882 |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
883 gxf->packet_count++; |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
884 if (gxf->packet_count == 100) { |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
885 gxf_write_map_packet(s, 0); |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
886 gxf->packet_count = 0; |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
887 } |
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
888 |
4674 | 889 put_flush_packet(pb); |
1183 | 890 |
4679
697b6a0366a6
write map packet every 100 packets according to specs
bcoudurier
parents:
4678
diff
changeset
|
891 return 0; |
1183 | 892 } |
893 | |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
894 static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cur) |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
895 { |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
896 GXFContext *gxf = s->priv_data; |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
897 AVPacket *pkt[2] = { cur, next }; |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
898 int i, field_nb[2]; |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
899 GXFStreamContext *sc[2]; |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
900 |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
901 for (i = 0; i < 2; i++) { |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
902 AVStream *st = s->streams[pkt[i]->stream_index]; |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
903 sc[i] = st->priv_data; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
904 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
905 field_nb[i] = av_rescale_rnd(pkt[i]->dts, gxf->time_base.den, |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
906 (int64_t)48000*gxf->time_base.num, AV_ROUND_UP); |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
907 field_nb[i] &= ~1; // compare against even field number because audio must be before video |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
908 } else |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
909 field_nb[i] = pkt[i]->dts; // dts are field based |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
910 } |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
911 |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
912 return field_nb[1] > field_nb[0] || |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
913 (field_nb[1] == field_nb[0] && sc[1]->order > sc[0]->order); |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
914 } |
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
915 |
1183 | 916 static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) |
917 { | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5290
diff
changeset
|
918 if (pkt && s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
919 pkt->duration = 2; // enforce 2 fields |
4426
7854590fb1fd
rename ff_audio_interleave to ff_audio_rechunk_interleave
bcoudurier
parents:
4401
diff
changeset
|
920 return ff_audio_rechunk_interleave(s, out, pkt, flush, |
4677
96c24e93b7d8
correctly interleave audio and video according to specs
bcoudurier
parents:
4676
diff
changeset
|
921 av_interleave_packet_per_dts, gxf_compare_field_nb); |
1183 | 922 } |
923 | |
924 AVOutputFormat gxf_muxer = { | |
925 "gxf", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3368
diff
changeset
|
926 NULL_IF_CONFIG_SMALL("GXF format"), |
1183 | 927 NULL, |
928 "gxf", | |
929 sizeof(GXFContext), | |
930 CODEC_ID_PCM_S16LE, | |
931 CODEC_ID_MPEG2VIDEO, | |
932 gxf_write_header, | |
933 gxf_write_packet, | |
934 gxf_write_trailer, | |
935 0, | |
936 NULL, | |
937 gxf_interleave_packet, | |
938 }; |