Mercurial > libavformat.hg
annotate gxfenc.c @ 4273:ed5196e6e112 libavformat
Move av_read_frame/parser related buffer variables from AVFormatContext
to AVStream, this is required if we want to allow the user to pull frames
from specific streams at some point in the future.
author | michael |
---|---|
date | Thu, 22 Jan 2009 23:35:31 +0000 |
parents | f146ce39977a |
children | d9c25a41b461 |
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 | |
3286 | 22 #include "libavutil/fifo.h" |
1183 | 23 #include "avformat.h" |
24 #include "gxf.h" | |
25 #include "riff.h" | |
26 | |
27 #define GXF_AUDIO_PACKET_SIZE 65536 | |
28 | |
29 typedef struct GXFStreamContext { | |
30 AVCodecContext *codec; | |
1322
95f56c7b24eb
* Moving FifoBuffer out of libavformat/avformat.h and
romansh
parents:
1262
diff
changeset
|
31 AVFifoBuffer audio_buffer; |
1183 | 32 uint32_t track_type; |
33 uint32_t sample_size; | |
34 uint32_t sample_rate; | |
35 uint16_t media_type; | |
36 uint16_t media_info; | |
37 uint8_t index; | |
38 int frame_rate_index; | |
39 int lines_index; | |
40 int fields; | |
41 int iframes; | |
42 int pframes; | |
43 int bframes; | |
44 int p_per_gop; | |
45 int b_per_gop; | |
1261 | 46 int first_gop_closed; |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
47 int64_t current_dts; |
1542 | 48 int dts_delay; |
1183 | 49 } GXFStreamContext; |
50 | |
51 typedef struct GXFContext { | |
52 uint32_t nb_frames; | |
53 uint32_t material_flags; | |
54 uint16_t audio_tracks; | |
55 uint16_t mpeg_tracks; | |
56 int64_t creation_time; | |
57 uint32_t umf_start_offset; | |
58 uint32_t umf_track_offset; | |
59 uint32_t umf_media_offset; | |
60 uint32_t umf_user_data_offset; | |
61 uint32_t umf_user_data_size; | |
62 uint32_t umf_length; | |
63 uint16_t umf_track_size; | |
64 uint16_t umf_media_size; | |
65 int audio_written; | |
66 int sample_rate; | |
67 int flags; | |
68 AVFormatContext *fc; | |
69 GXFStreamContext streams[48]; | |
70 } GXFContext; | |
71 | |
72 typedef struct GXF_Lines { | |
73 int height; | |
74 int index; | |
75 } GXF_Lines; | |
76 | |
77 | |
78 /* FIXME check if it is relevant */ | |
79 static const GXF_Lines gxf_lines_tab[] = { | |
80 { 480, 1 }, /* NTSC */ | |
81 { 512, 1 }, /* NTSC + VBI */ | |
82 { 576, 2 }, /* PAL */ | |
83 { 608, 2 }, /* PAL + VBI */ | |
84 { 1080, 4 }, | |
85 { 720, 6 }, | |
86 }; | |
87 | |
1677
2a85c82b8538
add codec_id <-> codec_tag tables to AVIn/OutputFormat
michael
parents:
1542
diff
changeset
|
88 static const AVCodecTag gxf_media_types[] = { |
1183 | 89 { CODEC_ID_MJPEG , 3 }, /* NTSC */ |
90 { CODEC_ID_MJPEG , 4 }, /* PAL */ | |
91 { CODEC_ID_PCM_S24LE , 9 }, | |
92 { CODEC_ID_PCM_S16LE , 10 }, | |
93 { CODEC_ID_MPEG2VIDEO, 11 }, /* NTSC */ | |
94 { CODEC_ID_MPEG2VIDEO, 12 }, /* PAL */ | |
95 { CODEC_ID_DVVIDEO , 13 }, /* NTSC */ | |
96 { CODEC_ID_DVVIDEO , 14 }, /* PAL */ | |
97 { CODEC_ID_DVVIDEO , 15 }, /* 50M NTSC */ | |
98 { CODEC_ID_DVVIDEO , 16 }, /* 50M PAL */ | |
99 { CODEC_ID_AC3 , 17 }, | |
100 //{ CODEC_ID_NONE, , 18 }, /* Non compressed 24 bit audio */ | |
101 { CODEC_ID_MPEG2VIDEO, 20 }, /* MPEG HD */ | |
102 { CODEC_ID_MPEG1VIDEO, 22 }, /* NTSC */ | |
103 { CODEC_ID_MPEG1VIDEO, 23 }, /* PAL */ | |
104 { 0, 0 }, | |
105 }; | |
106 | |
107 #define SERVER_PATH "/space/" | |
108 #define ES_NAME_PATTERN "ES." | |
109 | |
110 static int gxf_find_lines_index(GXFStreamContext *ctx) | |
111 { | |
112 int i; | |
113 | |
114 for (i = 0; i < 6; ++i) { | |
115 if (ctx->codec->height == gxf_lines_tab[i].height) { | |
116 ctx->lines_index = gxf_lines_tab[i].index; | |
117 return 0; | |
118 } | |
119 } | |
120 return -1; | |
121 } | |
122 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
123 static void gxf_write_padding(ByteIOContext *pb, int64_t to_pad) |
1183 | 124 { |
1213 | 125 for (; to_pad > 0; to_pad--) { |
1183 | 126 put_byte(pb, 0); |
127 } | |
128 } | |
129 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
130 static int64_t updatePacketSize(ByteIOContext *pb, int64_t pos) |
1183 | 131 { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
132 int64_t curpos; |
1183 | 133 int size; |
134 | |
135 size = url_ftell(pb) - pos; | |
136 if (size % 4) { | |
137 gxf_write_padding(pb, 4 - size % 4); | |
138 size = url_ftell(pb) - pos; | |
139 } | |
140 curpos = url_ftell(pb); | |
141 url_fseek(pb, pos + 6, SEEK_SET); | |
142 put_be32(pb, size); | |
143 url_fseek(pb, curpos, SEEK_SET); | |
144 return curpos - pos; | |
145 } | |
146 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
147 static int64_t updateSize(ByteIOContext *pb, int64_t pos) |
1183 | 148 { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
149 int64_t curpos; |
1183 | 150 |
151 curpos = url_ftell(pb); | |
152 url_fseek(pb, pos, SEEK_SET); | |
153 put_be16(pb, curpos - pos - 2); | |
154 url_fseek(pb, curpos, SEEK_SET); | |
155 return curpos - pos; | |
156 } | |
157 | |
4098 | 158 static void gxf_write_packet_header(ByteIOContext *pb, GXFPktType type) |
1183 | 159 { |
160 put_be32(pb, 0); /* packet leader for synchro */ | |
161 put_byte(pb, 1); | |
162 put_byte(pb, type); /* map packet */ | |
163 put_be32(pb, 0); /* size */ | |
164 put_be32(pb, 0); /* reserved */ | |
165 put_byte(pb, 0xE1); /* trailer 1 */ | |
166 put_byte(pb, 0xE2); /* trailer 2 */ | |
167 } | |
168 | |
169 static int gxf_write_mpeg_auxiliary(ByteIOContext *pb, GXFStreamContext *ctx) | |
170 { | |
171 char buffer[1024]; | |
4261 | 172 int size, starting_line; |
1183 | 173 |
174 if (ctx->iframes) { | |
175 ctx->p_per_gop = ctx->pframes / ctx->iframes; | |
176 if (ctx->pframes % ctx->iframes) | |
177 ctx->p_per_gop++; | |
178 if (ctx->pframes) | |
179 ctx->b_per_gop = ctx->bframes / ctx->pframes; | |
180 if (ctx->p_per_gop > 9) | |
181 ctx->p_per_gop = 9; /* ensure value won't take more than one char */ | |
182 if (ctx->b_per_gop > 9) | |
183 ctx->b_per_gop = 9; /* ensure value won't take more than one char */ | |
184 } | |
4261 | 185 if (ctx->codec->height == 512 || ctx->codec->height == 608) |
186 starting_line = 7; // VBI | |
187 else if (ctx->codec->height == 480) | |
188 starting_line = 20; | |
189 else | |
190 starting_line = 23; // default PAL | |
191 | |
1183 | 192 size = snprintf(buffer, 1024, "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n" |
4261 | 193 "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n", |
1183 | 194 (float)ctx->codec->bit_rate, ctx->p_per_gop, ctx->b_per_gop, |
1262 | 195 ctx->codec->pix_fmt == PIX_FMT_YUV422P ? 2 : 1, ctx->first_gop_closed == 1, |
4261 | 196 starting_line, ctx->codec->height / 16); |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
197 put_byte(pb, TRACK_MPG_AUX); |
1183 | 198 put_byte(pb, size + 1); |
199 put_buffer(pb, (uint8_t *)buffer, size + 1); | |
200 return size + 3; | |
201 } | |
202 | |
203 static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *ctx) | |
204 { | |
205 /* FIXME implement that */ | |
206 put_byte(pb, 0); /* fields */ | |
207 put_byte(pb, 0); /* seconds */ | |
208 put_byte(pb, 0); /* minutes */ | |
209 put_byte(pb, 0); /* flags + hours */ | |
210 /* reserved */ | |
211 put_be32(pb, 0); | |
212 return 8; | |
213 } | |
214 | |
215 static int gxf_write_track_description(ByteIOContext *pb, GXFStreamContext *stream) | |
216 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
217 int64_t pos; |
1183 | 218 |
219 /* track description section */ | |
220 put_byte(pb, stream->media_type + 0x80); | |
221 put_byte(pb, stream->index + 0xC0); | |
222 | |
223 pos = url_ftell(pb); | |
224 put_be16(pb, 0); /* size */ | |
225 | |
226 /* media file name */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
227 put_byte(pb, TRACK_NAME); |
1183 | 228 put_byte(pb, strlen(ES_NAME_PATTERN) + 3); |
229 put_tag(pb, ES_NAME_PATTERN); | |
230 put_be16(pb, stream->media_info); | |
231 put_byte(pb, 0); | |
232 | |
233 if (stream->codec->codec_id != CODEC_ID_MPEG2VIDEO) { | |
234 /* auxiliary information */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
235 put_byte(pb, TRACK_AUX); |
1183 | 236 put_byte(pb, 8); |
237 if (stream->codec->codec_id == CODEC_ID_NONE) | |
238 gxf_write_timecode_auxiliary(pb, stream); | |
239 else | |
240 put_le64(pb, 0); | |
241 } | |
242 | |
243 /* file system version */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
244 put_byte(pb, TRACK_VER); |
1183 | 245 put_byte(pb, 4); |
246 put_be32(pb, 0); | |
247 | |
248 if (stream->codec->codec_id == CODEC_ID_MPEG2VIDEO) | |
249 gxf_write_mpeg_auxiliary(pb, stream); | |
250 | |
251 /* frame rate */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
252 put_byte(pb, TRACK_FPS); |
1183 | 253 put_byte(pb, 4); |
254 put_be32(pb, stream->frame_rate_index); | |
255 | |
256 /* lines per frame */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
257 put_byte(pb, TRACK_LINES); |
1183 | 258 put_byte(pb, 4); |
259 put_be32(pb, stream->lines_index); | |
260 | |
261 /* fields per frame */ | |
2282
47f5906c30cc
replaces hardcoded values by the equivalent enum definitions
aurel
parents:
2252
diff
changeset
|
262 put_byte(pb, TRACK_FPF); |
1183 | 263 put_byte(pb, 4); |
264 put_be32(pb, stream->fields); | |
265 | |
266 return updateSize(pb, pos); | |
267 } | |
268 | |
269 static int gxf_write_material_data_section(ByteIOContext *pb, GXFContext *ctx) | |
270 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
271 int64_t pos; |
1183 | 272 const char *filename = strrchr(ctx->fc->filename, '/'); |
273 | |
274 pos = url_ftell(pb); | |
275 put_be16(pb, 0); /* size */ | |
276 | |
277 /* name */ | |
278 if (filename) | |
279 filename++; | |
280 else | |
281 filename = ctx->fc->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); |
296 put_be32(pb, ctx->nb_frames); | |
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); |
305 put_be32(pb, ctx->nb_frames); | |
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 | |
315 static int gxf_write_track_description_section(ByteIOContext *pb, GXFContext *ctx) | |
316 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
317 int64_t pos; |
1183 | 318 int i; |
319 | |
320 pos = url_ftell(pb); | |
321 put_be16(pb, 0); /* size */ | |
322 for (i = 0; i < ctx->fc->nb_streams; ++i) | |
323 gxf_write_track_description(pb, &ctx->streams[i]); | |
324 return updateSize(pb, pos); | |
325 } | |
326 | |
327 static int gxf_write_map_packet(ByteIOContext *pb, GXFContext *ctx) | |
328 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
329 int64_t pos = url_ftell(pb); |
1183 | 330 |
331 gxf_write_packet_header(pb, PKT_MAP); | |
332 | |
333 /* preamble */ | |
334 put_byte(pb, 0xE0); /* version */ | |
335 put_byte(pb, 0xFF); /* reserved */ | |
336 | |
337 gxf_write_material_data_section(pb, ctx); | |
338 gxf_write_track_description_section(pb, ctx); | |
339 | |
340 return updatePacketSize(pb, pos); | |
341 } | |
342 | |
343 #if 0 | |
344 static int gxf_write_flt_packet(ByteIOContext *pb, GXFContext *ctx) | |
345 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
346 int64_t pos = url_ftell(pb); |
1183 | 347 int i; |
348 | |
349 gxf_write_packet_header(pb, PKT_FLT); | |
350 | |
351 put_le32(pb, 1000); /* number of fields */ | |
352 put_le32(pb, 0); /* number of active flt entries */ | |
353 | |
354 for (i = 0; i < 1000; ++i) { | |
355 put_le32(pb, 0); | |
356 } | |
357 return updatePacketSize(pb, pos); | |
358 } | |
359 #endif | |
360 | |
361 static int gxf_write_umf_material_description(ByteIOContext *pb, GXFContext *ctx) | |
362 { | |
4260 | 363 // XXX drop frame |
364 int fps = ctx->sample_rate / 2; | |
365 int frames = ctx->nb_frames / 2; | |
366 uint32_t timecode = | |
367 frames % fps << 24 | // frames | |
368 frames / fps % 60 << 16 | // seconds | |
369 frames / fps * 60 % 60 << 8 | // minutes | |
370 frames / fps * 3600 % 24 << 3; // hours | |
371 | |
1183 | 372 put_le32(pb, ctx->flags); |
373 put_le32(pb, ctx->nb_frames); /* length of the longest track */ | |
374 put_le32(pb, ctx->nb_frames); /* length of the shortest track */ | |
375 put_le32(pb, 0); /* mark in */ | |
376 put_le32(pb, ctx->nb_frames); /* mark out */ | |
377 put_le32(pb, 0); /* timecode mark in */ | |
4260 | 378 put_le32(pb, timecode); /* timecode mark out */ |
1183 | 379 put_le64(pb, ctx->fc->timestamp); /* modification time */ |
380 put_le64(pb, ctx->fc->timestamp); /* creation time */ | |
381 put_le16(pb, 0); /* reserved */ | |
382 put_le16(pb, 0); /* reserved */ | |
383 put_le16(pb, ctx->audio_tracks); | |
384 put_le16(pb, 0); /* timecode track count */ | |
385 put_le16(pb, 0); /* reserved */ | |
386 put_le16(pb, ctx->mpeg_tracks); | |
387 return 48; | |
388 } | |
389 | |
390 static int gxf_write_umf_payload(ByteIOContext *pb, GXFContext *ctx) | |
391 { | |
392 put_le32(pb, ctx->umf_length); /* total length of the umf data */ | |
393 put_le32(pb, 3); /* version */ | |
394 put_le32(pb, ctx->fc->nb_streams); | |
395 put_le32(pb, ctx->umf_track_offset); /* umf track section offset */ | |
396 put_le32(pb, ctx->umf_track_size); | |
397 put_le32(pb, ctx->fc->nb_streams); | |
398 put_le32(pb, ctx->umf_media_offset); | |
399 put_le32(pb, ctx->umf_media_size); | |
400 put_le32(pb, ctx->umf_user_data_offset); /* user data offset */ | |
401 put_le32(pb, ctx->umf_user_data_size); /* user data size */ | |
402 put_le32(pb, 0); /* reserved */ | |
403 put_le32(pb, 0); /* reserved */ | |
404 return 48; | |
405 } | |
406 | |
407 static int gxf_write_umf_track_description(ByteIOContext *pb, GXFContext *ctx) | |
408 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
409 int64_t pos = url_ftell(pb); |
1183 | 410 int tracks[255]={0}; |
411 int i; | |
412 | |
413 ctx->umf_track_offset = pos - ctx->umf_start_offset; | |
414 for (i = 0; i < ctx->fc->nb_streams; ++i) { | |
415 AVStream *st = ctx->fc->streams[i]; | |
416 GXFStreamContext *sc = &ctx->streams[i]; | |
417 int id = 0; | |
418 | |
419 switch (st->codec->codec_id) { | |
420 case CODEC_ID_MPEG1VIDEO: id= 'L'; break; | |
421 case CODEC_ID_MPEG2VIDEO: id= 'M'; break; | |
422 case CODEC_ID_PCM_S16LE: id= 'A'; break; | |
423 case CODEC_ID_DVVIDEO: id= sc->track_type == 6 ? 'E' : 'D'; break; | |
424 case CODEC_ID_MJPEG: id= 'V'; break; | |
1361
37baab7af15a
quiet gcc about enum value not handled in switch
bcoudurier
parents:
1358
diff
changeset
|
425 default: break; |
1183 | 426 } |
427 sc->media_info= id << 8; | |
428 /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */ | |
429 sc->media_info |= '0' + (tracks[id]++); | |
430 put_le16(pb, sc->media_info); | |
431 put_le16(pb, 1); | |
432 } | |
433 return url_ftell(pb) - pos; | |
434 } | |
435 | |
436 static int gxf_write_umf_media_mpeg(ByteIOContext *pb, GXFStreamContext *stream) | |
437 { | |
438 if (stream->codec->pix_fmt == PIX_FMT_YUV422P) | |
439 put_le32(pb, 2); | |
440 else | |
441 put_le32(pb, 1); /* default to 420 */ | |
1262 | 442 put_le32(pb, stream->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */ |
1183 | 443 put_le32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */ |
444 put_le32(pb, 1); /* I picture per GOP */ | |
445 put_le32(pb, stream->p_per_gop); | |
446 put_le32(pb, stream->b_per_gop); | |
447 if (stream->codec->codec_id == CODEC_ID_MPEG2VIDEO) | |
448 put_le32(pb, 2); | |
449 else if (stream->codec->codec_id == CODEC_ID_MPEG1VIDEO) | |
450 put_le32(pb, 1); | |
451 else | |
452 put_le32(pb, 0); | |
453 put_le32(pb, 0); /* reserved */ | |
454 return 32; | |
455 } | |
456 | |
457 static int gxf_write_umf_media_timecode(ByteIOContext *pb, GXFStreamContext *track) | |
458 { | |
459 /* FIXME implement */ | |
460 put_be32(pb, 0); /* drop frame flag */ | |
461 put_be32(pb, 0); /* reserved */ | |
462 put_be32(pb, 0); /* reserved */ | |
463 put_be32(pb, 0); /* reserved */ | |
464 put_be32(pb, 0); /* reserved */ | |
465 put_be32(pb, 0); /* reserved */ | |
466 put_be32(pb, 0); /* reserved */ | |
467 put_be32(pb, 0); /* reserved */ | |
468 return 32; | |
469 } | |
470 | |
471 static int gxf_write_umf_media_dv(ByteIOContext *pb, GXFStreamContext *track) | |
472 { | |
473 int i; | |
474 | |
475 for (i = 0; i < 8; i++) { | |
476 put_be32(pb, 0); | |
477 } | |
478 return 32; | |
479 } | |
480 | |
481 static int gxf_write_umf_media_audio(ByteIOContext *pb, GXFStreamContext *track) | |
482 { | |
483 put_le64(pb, av_dbl2int(1)); /* sound level to begin to */ | |
484 put_le64(pb, av_dbl2int(1)); /* sound level to begin to */ | |
485 put_le32(pb, 0); /* number of fields over which to ramp up sound level */ | |
486 put_le32(pb, 0); /* number of fields over which to ramp down sound level */ | |
487 put_le32(pb, 0); /* reserved */ | |
488 put_le32(pb, 0); /* reserved */ | |
489 return 32; | |
490 } | |
491 | |
492 #if 0 | |
493 static int gxf_write_umf_media_mjpeg(ByteIOContext *pb, GXFStreamContext *track) | |
494 { | |
495 put_be64(pb, 0); /* FIXME FLOAT max chroma quant level */ | |
496 put_be64(pb, 0); /* FIXME FLOAT max luma quant level */ | |
497 put_be64(pb, 0); /* FIXME FLOAT min chroma quant level */ | |
498 put_be64(pb, 0); /* FIXME FLOAT min luma quant level */ | |
499 return 32; | |
500 } | |
501 #endif | |
502 | |
503 static int gxf_write_umf_media_description(ByteIOContext *pb, GXFContext *ctx) | |
504 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
505 int64_t pos; |
1183 | 506 int i; |
507 | |
508 pos = url_ftell(pb); | |
509 ctx->umf_media_offset = pos - ctx->umf_start_offset; | |
510 for (i = 0; i < ctx->fc->nb_streams; ++i) { | |
511 GXFStreamContext *sc = &ctx->streams[i]; | |
512 char buffer[88]; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
513 int64_t startpos, curpos; |
1183 | 514 int path_size = strlen(ES_NAME_PATTERN); |
515 | |
1260 | 516 memset(buffer, 0, 88); |
1183 | 517 startpos = url_ftell(pb); |
518 put_le16(pb, 0); /* length */ | |
519 put_le16(pb, sc->media_info); | |
520 put_le16(pb, 0); /* reserved */ | |
521 put_le16(pb, 0); /* reserved */ | |
522 put_le32(pb, ctx->nb_frames); | |
523 put_le32(pb, 0); /* attributes rw, ro */ | |
524 put_le32(pb, 0); /* mark in */ | |
525 put_le32(pb, ctx->nb_frames); /* mark out */ | |
526 strncpy(buffer, ES_NAME_PATTERN, path_size); | |
527 put_buffer(pb, (uint8_t *)buffer, path_size); | |
528 put_be16(pb, sc->media_info); | |
529 put_buffer(pb, (uint8_t *)buffer + path_size + 2, 88 - path_size - 2); | |
530 put_le32(pb, sc->track_type); | |
531 put_le32(pb, sc->sample_rate); | |
532 put_le32(pb, sc->sample_size); | |
533 put_le32(pb, 0); /* reserved */ | |
534 switch (sc->codec->codec_id) { | |
535 case CODEC_ID_MPEG2VIDEO: | |
536 gxf_write_umf_media_mpeg(pb, sc); | |
537 break; | |
538 case CODEC_ID_PCM_S16LE: | |
539 gxf_write_umf_media_audio(pb, sc); | |
540 break; | |
541 case CODEC_ID_DVVIDEO: | |
542 gxf_write_umf_media_dv(pb, sc); | |
543 break; | |
544 default: | |
545 gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */ | |
546 } | |
547 curpos = url_ftell(pb); | |
548 url_fseek(pb, startpos, SEEK_SET); | |
549 put_le16(pb, curpos - startpos); | |
550 url_fseek(pb, curpos, SEEK_SET); | |
551 } | |
552 return url_ftell(pb) - pos; | |
553 } | |
554 | |
555 static int gxf_write_umf_user_data(ByteIOContext *pb, GXFContext *ctx) | |
556 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
557 int64_t pos = url_ftell(pb); |
1183 | 558 ctx->umf_user_data_offset = pos - ctx->umf_start_offset; |
559 put_le32(pb, 20); | |
560 put_le32(pb, 0); | |
561 put_le16(pb, 0); | |
562 put_le16(pb, 0); | |
563 put_le32(pb, 0); | |
564 put_byte(pb, 0); | |
565 put_byte(pb, 0); | |
566 put_byte(pb, 0); | |
567 put_byte(pb, 0); | |
568 return 20; | |
569 } | |
570 | |
571 static int gxf_write_umf_packet(ByteIOContext *pb, GXFContext *ctx) | |
572 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
573 int64_t pos = url_ftell(pb); |
1183 | 574 |
575 gxf_write_packet_header(pb, PKT_UMF); | |
576 | |
577 /* preamble */ | |
578 put_byte(pb, 3); /* first and last (only) packet */ | |
579 put_be32(pb, ctx->umf_length); /* data length */ | |
580 | |
581 ctx->umf_start_offset = url_ftell(pb); | |
582 gxf_write_umf_payload(pb, ctx); | |
583 gxf_write_umf_material_description(pb, ctx); | |
584 ctx->umf_track_size = gxf_write_umf_track_description(pb, ctx); | |
585 ctx->umf_media_size = gxf_write_umf_media_description(pb, ctx); | |
586 ctx->umf_user_data_size = gxf_write_umf_user_data(pb, ctx); | |
587 ctx->umf_length = url_ftell(pb) - ctx->umf_start_offset; | |
588 return updatePacketSize(pb, pos); | |
589 } | |
590 | |
1794 | 591 #define GXF_NODELAY -5000 |
592 | |
1183 | 593 static int gxf_write_header(AVFormatContext *s) |
594 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2337
diff
changeset
|
595 ByteIOContext *pb = s->pb; |
1183 | 596 GXFContext *gxf = s->priv_data; |
597 int i; | |
598 | |
599 gxf->fc = s; | |
600 gxf->flags |= 0x00080000; /* material is simple clip */ | |
601 for (i = 0; i < s->nb_streams; ++i) { | |
602 AVStream *st = s->streams[i]; | |
603 GXFStreamContext *sc = &gxf->streams[i]; | |
604 | |
605 sc->codec = st->codec; | |
606 sc->index = i; | |
607 sc->media_type = codec_get_tag(gxf_media_types, sc->codec->codec_id); | |
608 if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
609 if (st->codec->codec_id != CODEC_ID_PCM_S16LE) { | |
610 av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n"); | |
611 return -1; | |
612 } | |
613 if (st->codec->sample_rate != 48000) { | |
614 av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n"); | |
615 return -1; | |
616 } | |
617 if (st->codec->channels != 1) { | |
618 av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n"); | |
619 return -1; | |
620 } | |
621 sc->track_type = 2; | |
622 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
|
623 av_set_pts_info(st, 64, 1, sc->sample_rate); |
1183 | 624 sc->sample_size = 16; |
625 sc->frame_rate_index = -2; | |
626 sc->lines_index = -2; | |
627 sc->fields = -2; | |
628 gxf->audio_tracks++; | |
629 gxf->flags |= 0x04000000; /* audio is 16 bit pcm */ | |
1322
95f56c7b24eb
* Moving FifoBuffer out of libavformat/avformat.h and
romansh
parents:
1262
diff
changeset
|
630 av_fifo_init(&sc->audio_buffer, 3*GXF_AUDIO_PACKET_SIZE); |
1183 | 631 } else if (sc->codec->codec_type == CODEC_TYPE_VIDEO) { |
632 /* FIXME check from time_base ? */ | |
633 if (sc->codec->height == 480 || sc->codec->height == 512) { /* NTSC or NTSC+VBI */ | |
634 sc->frame_rate_index = 5; | |
635 sc->sample_rate = 60; | |
636 gxf->flags |= 0x00000080; | |
637 } else { /* assume PAL */ | |
638 sc->frame_rate_index = 6; | |
639 sc->media_type++; | |
640 sc->sample_rate = 50; | |
641 gxf->flags |= 0x00000040; | |
642 } | |
643 gxf->sample_rate = sc->sample_rate; | |
1794 | 644 av_set_pts_info(st, 64, 1, st->codec->time_base.den); |
645 sc->dts_delay = GXF_NODELAY; | |
1183 | 646 if (gxf_find_lines_index(sc) < 0) |
647 sc->lines_index = -1; | |
648 sc->sample_size = st->codec->bit_rate; | |
649 sc->fields = 2; /* interlaced */ | |
650 switch (sc->codec->codec_id) { | |
651 case CODEC_ID_MPEG2VIDEO: | |
1262 | 652 sc->first_gop_closed = -1; |
1183 | 653 sc->track_type = 4; |
654 gxf->mpeg_tracks++; | |
655 gxf->flags |= 0x00008000; | |
656 break; | |
657 case CODEC_ID_DVVIDEO: | |
658 if (sc->codec->pix_fmt == PIX_FMT_YUV422P) { | |
659 sc->media_type += 2; | |
660 sc->track_type = 6; | |
661 gxf->flags |= 0x00002000; | |
662 } else { | |
663 sc->track_type = 5; | |
664 gxf->flags |= 0x00001000; | |
665 } | |
666 break; | |
667 default: | |
1401 | 668 av_log(s, AV_LOG_ERROR, "video codec not supported\n"); |
1183 | 669 return -1; |
670 } | |
671 } | |
672 } | |
673 gxf_write_map_packet(pb, gxf); | |
674 //gxf_write_flt_packet(pb, gxf); | |
675 gxf_write_umf_packet(pb, gxf); | |
676 put_flush_packet(pb); | |
677 return 0; | |
678 } | |
679 | |
680 static int gxf_write_eos_packet(ByteIOContext *pb, GXFContext *ctx) | |
681 { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
682 int64_t pos = url_ftell(pb); |
1183 | 683 |
684 gxf_write_packet_header(pb, PKT_EOS); | |
685 return updatePacketSize(pb, pos); | |
686 } | |
687 | |
688 static int gxf_write_trailer(AVFormatContext *s) | |
689 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2337
diff
changeset
|
690 ByteIOContext *pb = s->pb; |
1183 | 691 GXFContext *gxf = s->priv_data; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
692 int64_t end; |
1183 | 693 int i; |
694 | |
695 for (i = 0; i < s->nb_streams; ++i) { | |
4262
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
696 if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) |
1322
95f56c7b24eb
* Moving FifoBuffer out of libavformat/avformat.h and
romansh
parents:
1262
diff
changeset
|
697 av_fifo_free(&gxf->streams[i].audio_buffer); |
1183 | 698 } |
699 | |
700 gxf_write_eos_packet(pb, gxf); | |
701 end = url_ftell(pb); | |
702 url_fseek(pb, 0, SEEK_SET); | |
703 /* overwrite map and umf packets with new values */ | |
704 gxf_write_map_packet(pb, gxf); | |
705 //gxf_write_flt_packet(pb, gxf); | |
706 gxf_write_umf_packet(pb, gxf); | |
707 url_fseek(pb, end, SEEK_SET); | |
708 return 0; | |
709 } | |
710 | |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
711 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
|
712 { |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
713 uint32_t c=-1; |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
714 int i; |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
715 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
|
716 c = (c<<8) + buf[i]; |
1262 | 717 if(c == 0x1B8 && sc->first_gop_closed == -1) /* GOP start code */ |
1261 | 718 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
|
719 } |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
720 return (buf[i+1]>>3)&7; |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
721 } |
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
722 |
1183 | 723 static int gxf_write_media_preamble(ByteIOContext *pb, GXFContext *ctx, AVPacket *pkt, int size) |
724 { | |
725 GXFStreamContext *sc = &ctx->streams[pkt->stream_index]; | |
2251
b7950418654d
round timestamps up, k2 broadcast server seems to need it
bcoudurier
parents:
1794
diff
changeset
|
726 int64_t dts = av_rescale_rnd(pkt->dts, ctx->sample_rate, sc->codec->time_base.den, AV_ROUND_UP); |
1183 | 727 |
728 put_byte(pb, sc->media_type); | |
729 put_byte(pb, sc->index); | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
730 put_be32(pb, dts); |
1183 | 731 if (sc->codec->codec_type == CODEC_TYPE_AUDIO) { |
732 put_be16(pb, 0); | |
733 put_be16(pb, size / 2); | |
734 } else if (sc->codec->codec_id == CODEC_ID_MPEG2VIDEO) { | |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
735 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
|
736 if (frame_type == FF_I_TYPE) { |
1183 | 737 put_byte(pb, 0x0d); |
738 sc->iframes++; | |
1247
2f118b3e65c6
parse mpeg frame to get pict type and closed gop flag
bcoudurier
parents:
1213
diff
changeset
|
739 } else if (frame_type == FF_B_TYPE) { |
1183 | 740 put_byte(pb, 0x0f); |
741 sc->bframes++; | |
742 } else { | |
743 put_byte(pb, 0x0e); | |
744 sc->pframes++; | |
745 } | |
746 put_be24(pb, size); | |
747 } else if (sc->codec->codec_id == CODEC_ID_DVVIDEO) { | |
748 put_byte(pb, size / 4096); | |
749 put_be24(pb, 0); | |
750 } else | |
751 put_be32(pb, size); | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
752 put_be32(pb, dts); |
1183 | 753 put_byte(pb, 1); /* flags */ |
754 put_byte(pb, 0); /* reserved */ | |
755 return 16; | |
756 } | |
757 | |
758 static int gxf_write_media_packet(ByteIOContext *pb, GXFContext *ctx, AVPacket *pkt) | |
759 { | |
760 GXFStreamContext *sc = &ctx->streams[pkt->stream_index]; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3424
diff
changeset
|
761 int64_t pos = url_ftell(pb); |
1183 | 762 int padding = 0; |
763 | |
764 gxf_write_packet_header(pb, PKT_MEDIA); | |
765 if (sc->codec->codec_id == CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */ | |
766 padding = 4 - pkt->size % 4; | |
1212 | 767 else if (sc->codec->codec_type == CODEC_TYPE_AUDIO) |
768 padding = GXF_AUDIO_PACKET_SIZE - pkt->size; | |
1183 | 769 gxf_write_media_preamble(pb, ctx, pkt, pkt->size + padding); |
1212 | 770 put_buffer(pb, pkt->data, pkt->size); |
771 gxf_write_padding(pb, padding); | |
4262
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
772 |
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
773 if (sc->codec->codec_type == CODEC_TYPE_VIDEO) |
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
774 ctx->nb_frames += 2; // count fields |
f146ce39977a
Do not use avctx->frame_number which might not be set,
bcoudurier
parents:
4261
diff
changeset
|
775 |
1183 | 776 return updatePacketSize(pb, pos); |
777 } | |
778 | |
779 static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt) | |
780 { | |
781 GXFContext *gxf = s->priv_data; | |
782 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2337
diff
changeset
|
783 gxf_write_media_packet(s->pb, gxf, pkt); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2337
diff
changeset
|
784 put_flush_packet(s->pb); |
1183 | 785 return 0; |
786 } | |
787 | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
788 static int gxf_new_audio_packet(GXFContext *gxf, GXFStreamContext *sc, AVPacket *pkt, int flush) |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
789 { |
1322
95f56c7b24eb
* Moving FifoBuffer out of libavformat/avformat.h and
romansh
parents:
1262
diff
changeset
|
790 int size = flush ? av_fifo_size(&sc->audio_buffer) : GXF_AUDIO_PACKET_SIZE; |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
791 |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
792 if (!size) |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
793 return 0; |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
794 av_new_packet(pkt, size); |
1322
95f56c7b24eb
* Moving FifoBuffer out of libavformat/avformat.h and
romansh
parents:
1262
diff
changeset
|
795 av_fifo_read(&sc->audio_buffer, pkt->data, size); |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
796 pkt->stream_index = sc->index; |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
797 pkt->dts = sc->current_dts; |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
798 sc->current_dts += size / 2; /* we only support 16 bit pcm mono for now */ |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
799 return size; |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
800 } |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
801 |
1183 | 802 static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) |
803 { | |
804 GXFContext *gxf = s->priv_data; | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
805 AVPacket new_pkt; |
1183 | 806 int i; |
807 | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
808 for (i = 0; i < s->nb_streams; i++) { |
1542 | 809 AVStream *st = s->streams[i]; |
810 GXFStreamContext *sc = &gxf->streams[i]; | |
811 if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
812 if (pkt && pkt->stream_index == i) { |
3368
4a233106ccd0
use av_fifo_generic_write, old func is deprecated
bcoudurier
parents:
3286
diff
changeset
|
813 av_fifo_generic_write(&sc->audio_buffer, pkt->data, pkt->size, NULL); |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
814 pkt = NULL; |
1183 | 815 } |
1322
95f56c7b24eb
* Moving FifoBuffer out of libavformat/avformat.h and
romansh
parents:
1262
diff
changeset
|
816 if (flush || av_fifo_size(&sc->audio_buffer) >= GXF_AUDIO_PACKET_SIZE) { |
1398 | 817 if (!pkt && gxf_new_audio_packet(gxf, sc, &new_pkt, flush) > 0) { |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
818 pkt = &new_pkt; |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
819 break; /* add pkt right now into list */ |
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
820 } |
1183 | 821 } |
1794 | 822 } else if (pkt && pkt->stream_index == i) { |
823 if (sc->dts_delay == GXF_NODELAY) /* adjust dts if needed */ | |
824 sc->dts_delay = pkt->dts; | |
1542 | 825 pkt->dts -= sc->dts_delay; |
1183 | 826 } |
827 } | |
1253
f3d5e1c49875
use packet dts as correct media field number and use av_interleave_pkt_per_dts
bcoudurier
parents:
1247
diff
changeset
|
828 return av_interleave_packet_per_dts(s, out, pkt, flush); |
1183 | 829 } |
830 | |
831 AVOutputFormat gxf_muxer = { | |
832 "gxf", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3368
diff
changeset
|
833 NULL_IF_CONFIG_SMALL("GXF format"), |
1183 | 834 NULL, |
835 "gxf", | |
836 sizeof(GXFContext), | |
837 CODEC_ID_PCM_S16LE, | |
838 CODEC_ID_MPEG2VIDEO, | |
839 gxf_write_header, | |
840 gxf_write_packet, | |
841 gxf_write_trailer, | |
842 0, | |
843 NULL, | |
844 gxf_interleave_packet, | |
845 }; |