FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/gxfenc.c
Date: 2024-10-17 22:24:08
Exec Total Coverage
Lines: 497 592 84.0%
Functions: 31 33 93.9%
Branches: 120 181 66.3%

Line Branch Exec Source
1 /*
2 * GXF muxer.
3 * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "libavutil/avassert.h"
23 #include "libavutil/intfloat.h"
24 #include "libavutil/mathematics.h"
25 #include "libavutil/mem.h"
26 #include "avformat.h"
27 #include "avio_internal.h"
28 #include "internal.h"
29 #include "gxf.h"
30 #include "mux.h"
31
32 #define GXF_SAMPLES_PER_FRAME 32768
33 #define GXF_AUDIO_PACKET_SIZE 65536
34
35 #define GXF_TIMECODE(c, d, h, m, s, f) \
36 ((c) << 30 | (d) << 29 | (h) << 24 | (m) << 16 | (s) << 8 | (f))
37
38 typedef struct GXFTimecode{
39 int hh;
40 int mm;
41 int ss;
42 int ff;
43 int color;
44 int drop;
45 } GXFTimecode;
46
47 typedef struct GXFStreamContext {
48 int64_t pkt_cnt;
49 uint32_t track_type;
50 uint32_t sample_size;
51 uint32_t sample_rate;
52 uint16_t media_type;
53 uint16_t media_info;
54 int frame_rate_index;
55 int lines_index;
56 int fields;
57 int iframes;
58 int pframes;
59 int bframes;
60 int p_per_gop;
61 int b_per_i_or_p; ///< number of B-frames per I-frame or P-frame
62 int first_gop_closed;
63 unsigned order; ///< interleaving order
64 } GXFStreamContext;
65
66 typedef struct GXFContext {
67 AVClass *av_class;
68 uint32_t nb_fields;
69 uint16_t audio_tracks;
70 uint16_t mpeg_tracks;
71 int64_t creation_time;
72 uint32_t umf_start_offset;
73 uint32_t umf_track_offset;
74 uint32_t umf_media_offset;
75 uint32_t umf_length;
76 uint16_t umf_track_size;
77 uint16_t umf_media_size;
78 AVRational time_base;
79 int flags;
80 GXFStreamContext timecode_track;
81 unsigned *flt_entries; ///< offsets of packets /1024, starts after 2nd video field
82 unsigned flt_entries_nb;
83 uint64_t *map_offsets; ///< offset of map packets
84 unsigned map_offsets_nb;
85 unsigned packet_count;
86 GXFTimecode tc;
87 } GXFContext;
88
89 static const struct {
90 int height, index;
91 } gxf_lines_tab[] = {
92 { 480, 1 }, /* NTSC */
93 { 512, 1 }, /* NTSC + VBI */
94 { 576, 2 }, /* PAL */
95 { 608, 2 }, /* PAL + VBI */
96 { 1080, 4 },
97 { 720, 6 },
98 };
99
100 static const AVCodecTag gxf_media_types[] = {
101 { AV_CODEC_ID_MJPEG , 3 }, /* NTSC */
102 { AV_CODEC_ID_MJPEG , 4 }, /* PAL */
103 { AV_CODEC_ID_PCM_S24LE , 9 },
104 { AV_CODEC_ID_PCM_S16LE , 10 },
105 { AV_CODEC_ID_MPEG2VIDEO, 11 }, /* NTSC */
106 { AV_CODEC_ID_MPEG2VIDEO, 12 }, /* PAL */
107 { AV_CODEC_ID_DVVIDEO , 13 }, /* NTSC */
108 { AV_CODEC_ID_DVVIDEO , 14 }, /* PAL */
109 { AV_CODEC_ID_DVVIDEO , 15 }, /* 50M NTSC */
110 { AV_CODEC_ID_DVVIDEO , 16 }, /* 50M PAL */
111 { AV_CODEC_ID_AC3 , 17 },
112 //{ AV_CODEC_ID_NONE, , 18 }, /* Non compressed 24 bit audio */
113 { AV_CODEC_ID_MPEG2VIDEO, 20 }, /* MPEG HD */
114 { AV_CODEC_ID_MPEG1VIDEO, 22 }, /* NTSC */
115 { AV_CODEC_ID_MPEG1VIDEO, 23 }, /* PAL */
116 { AV_CODEC_ID_NONE, 0 },
117 };
118
119 #define SERVER_PATH "EXT:/PDR/default/"
120 #define ES_NAME_PATTERN "EXT:/PDR/default/ES."
121
122 3 static int gxf_find_lines_index(AVStream *st)
123 {
124 3 GXFStreamContext *sc = st->priv_data;
125 int i;
126
127
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 for (i = 0; i < 6; ++i) {
128
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (st->codecpar->height == gxf_lines_tab[i].height) {
129 3 sc->lines_index = gxf_lines_tab[i].index;
130 3 return 0;
131 }
132 }
133 return -1;
134 }
135
136 98 static void gxf_write_padding(AVIOContext *pb, int64_t to_pad)
137 {
138 98 ffio_fill(pb, 0, to_pad);
139 98 }
140
141 107 static int64_t update_packet_size(AVIOContext *pb, int64_t pos)
142 {
143 int64_t curpos;
144 int size;
145
146 107 size = avio_tell(pb) - pos;
147
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 95 times.
107 if (size % 4) {
148 12 gxf_write_padding(pb, 4 - size % 4);
149 12 size = avio_tell(pb) - pos;
150 }
151 107 curpos = avio_tell(pb);
152 107 avio_seek(pb, pos + 6, SEEK_SET);
153 107 avio_wb32(pb, size);
154 107 avio_seek(pb, curpos, SEEK_SET);
155 107 return curpos - pos;
156 }
157
158 30 static int64_t update_size(AVIOContext *pb, int64_t pos)
159 {
160 int64_t curpos;
161
162 30 curpos = avio_tell(pb);
163 30 avio_seek(pb, pos, SEEK_SET);
164 30 avio_wb16(pb, curpos - pos - 2);
165 30 avio_seek(pb, curpos, SEEK_SET);
166 30 return curpos - pos;
167 }
168
169 107 static void gxf_write_packet_header(AVIOContext *pb, GXFPktType type)
170 {
171 107 avio_wb32(pb, 0); /* packet leader for synchro */
172 107 avio_w8(pb, 1);
173 107 avio_w8(pb, type); /* map packet */
174 107 avio_wb32(pb, 0); /* size */
175 107 avio_wb32(pb, 0); /* reserved */
176 107 avio_w8(pb, 0xE1); /* trailer 1 */
177 107 avio_w8(pb, 0xE2); /* trailer 2 */
178 107 }
179
180 6 static int gxf_write_mpeg_auxiliary(AVIOContext *pb, AVStream *st)
181 {
182 6 GXFStreamContext *sc = st->priv_data;
183 char buffer[1024];
184 int size, starting_line;
185
186
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (sc->iframes) {
187 3 sc->p_per_gop = sc->pframes / sc->iframes;
188
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (sc->pframes % sc->iframes)
189 2 sc->p_per_gop++;
190
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->pframes) {
191 3 sc->b_per_i_or_p = sc->bframes / sc->pframes;
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->bframes % sc->pframes)
193 sc->b_per_i_or_p++;
194 }
195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->p_per_gop > 9)
196 sc->p_per_gop = 9; /* ensure value won't take more than one char */
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sc->b_per_i_or_p > 9)
198 sc->b_per_i_or_p = 9; /* ensure value won't take more than one char */
199 }
200
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (st->codecpar->height == 512 || st->codecpar->height == 608)
201 starting_line = 7; // VBI
202
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 else if (st->codecpar->height == 480)
203 2 starting_line = 20;
204 else
205 4 starting_line = 23; // default PAL
206
207 6 size = snprintf(buffer, sizeof(buffer), "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n"
208 "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n",
209 6 (float)st->codecpar->bit_rate, sc->p_per_gop, sc->b_per_i_or_p,
210 6 st->codecpar->format == AV_PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1,
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 starting_line, (st->codecpar->height + 15) / 16);
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 av_assert0(size < sizeof(buffer));
213 6 avio_w8(pb, TRACK_MPG_AUX);
214 6 avio_w8(pb, size + 1);
215 6 avio_write(pb, (uint8_t *)buffer, size + 1);
216 6 return size + 3;
217 }
218
219 static int gxf_write_dv_auxiliary(AVIOContext *pb, AVStream *st)
220 {
221 int64_t track_aux_data = 0;
222
223 avio_w8(pb, TRACK_AUX);
224 avio_w8(pb, 8);
225 if (st->codecpar->format == AV_PIX_FMT_YUV420P)
226 track_aux_data |= 0x01; /* marks stream as DVCAM instead of DVPRO */
227 track_aux_data |= 0x40000000; /* aux data is valid */
228 avio_wl64(pb, track_aux_data);
229 return 8;
230 }
231
232 6 static int gxf_write_timecode_auxiliary(AVIOContext *pb, GXFContext *gxf)
233 {
234 6 uint32_t timecode = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop,
235 gxf->tc.hh, gxf->tc.mm,
236 gxf->tc.ss, gxf->tc.ff);
237
238 6 avio_w8(pb, TRACK_AUX);
239 6 avio_w8(pb, 8);
240 6 avio_wl32(pb, timecode);
241 /* reserved */
242 6 avio_wl32(pb, 0);
243 6 return 8;
244 }
245
246 18 static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, int index)
247 {
248 18 GXFContext *gxf = s->priv_data;
249 18 AVIOContext *pb = s->pb;
250 int64_t pos;
251
252 /* track description section */
253 18 avio_w8(pb, sc->media_type + 0x80);
254 18 avio_w8(pb, index + 0xC0);
255
256 18 pos = avio_tell(pb);
257 18 avio_wb16(pb, 0); /* size */
258
259 /* media file name */
260 18 avio_w8(pb, TRACK_NAME);
261 18 avio_w8(pb, strlen(ES_NAME_PATTERN) + 3);
262 18 avio_write(pb, ES_NAME_PATTERN, sizeof(ES_NAME_PATTERN) - 1);
263 18 avio_wb16(pb, sc->media_info);
264 18 avio_w8(pb, 0);
265
266
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
18 switch (sc->track_type) {
267 6 case 3: /* timecode */
268 6 gxf_write_timecode_auxiliary(pb, gxf);
269 6 break;
270 6 case 4: /* MPEG2 */
271 case 9: /* MPEG1 */
272 6 gxf_write_mpeg_auxiliary(pb, s->streams[index]);
273 6 break;
274 case 5: /* DV25 */
275 case 6: /* DV50 */
276 gxf_write_dv_auxiliary(pb, s->streams[index]);
277 break;
278 6 default:
279 6 avio_w8(pb, TRACK_AUX);
280 6 avio_w8(pb, 8);
281 6 avio_wl64(pb, 0);
282 }
283
284 /* file system version */
285 18 avio_w8(pb, TRACK_VER);
286 18 avio_w8(pb, 4);
287 18 avio_wb32(pb, 0);
288
289 /* frame rate */
290 18 avio_w8(pb, TRACK_FPS);
291 18 avio_w8(pb, 4);
292 18 avio_wb32(pb, sc->frame_rate_index);
293
294 /* lines per frame */
295 18 avio_w8(pb, TRACK_LINES);
296 18 avio_w8(pb, 4);
297 18 avio_wb32(pb, sc->lines_index);
298
299 /* fields per frame */
300 18 avio_w8(pb, TRACK_FPF);
301 18 avio_w8(pb, 4);
302 18 avio_wb32(pb, sc->fields);
303
304 18 return update_size(pb, pos);
305 }
306
307 6 static int gxf_write_material_data_section(AVFormatContext *s)
308 {
309 6 GXFContext *gxf = s->priv_data;
310 6 AVIOContext *pb = s->pb;
311 int64_t pos;
312 int len;
313 6 const char *filename = strrchr(s->url, '/');
314
315 6 pos = avio_tell(pb);
316 6 avio_wb16(pb, 0); /* size */
317
318 /* name */
319
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (filename)
320 6 filename++;
321 else
322 filename = s->url;
323 6 len = strlen(filename);
324
325 6 avio_w8(pb, MAT_NAME);
326 6 avio_w8(pb, strlen(SERVER_PATH) + len + 1);
327 6 avio_write(pb, SERVER_PATH, sizeof(SERVER_PATH) - 1);
328 6 avio_write(pb, filename, len);
329 6 avio_w8(pb, 0);
330
331 /* first field */
332 6 avio_w8(pb, MAT_FIRST_FIELD);
333 6 avio_w8(pb, 4);
334 6 avio_wb32(pb, 0);
335
336 /* last field */
337 6 avio_w8(pb, MAT_LAST_FIELD);
338 6 avio_w8(pb, 4);
339 6 avio_wb32(pb, gxf->nb_fields);
340
341 /* reserved */
342 6 avio_w8(pb, MAT_MARK_IN);
343 6 avio_w8(pb, 4);
344 6 avio_wb32(pb, 0);
345
346 6 avio_w8(pb, MAT_MARK_OUT);
347 6 avio_w8(pb, 4);
348 6 avio_wb32(pb, gxf->nb_fields);
349
350 /* estimated size */
351 6 avio_w8(pb, MAT_SIZE);
352 6 avio_w8(pb, 4);
353 6 avio_wb32(pb, avio_size(pb) / 1024);
354
355 6 return update_size(pb, pos);
356 }
357
358 6 static int gxf_write_track_description_section(AVFormatContext *s)
359 {
360 6 GXFContext *gxf = s->priv_data;
361 6 AVIOContext *pb = s->pb;
362 int64_t pos;
363 int i;
364
365 6 pos = avio_tell(pb);
366 6 avio_wb16(pb, 0); /* size */
367
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (i = 0; i < s->nb_streams; ++i)
368 12 gxf_write_track_description(s, s->streams[i]->priv_data, i);
369
370 6 gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams);
371
372 6 return update_size(pb, pos);
373 }
374
375 6 static int gxf_write_map_packet(AVFormatContext *s, int rewrite)
376 {
377 6 GXFContext *gxf = s->priv_data;
378 6 AVIOContext *pb = s->pb;
379 6 int64_t pos = avio_tell(pb);
380
381
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!rewrite) {
382
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!(gxf->map_offsets_nb % 30)) {
383 int err;
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if ((err = av_reallocp_array(&gxf->map_offsets,
385 3 gxf->map_offsets_nb + 30,
386 sizeof(*gxf->map_offsets))) < 0) {
387 gxf->map_offsets_nb = 0;
388 av_log(s, AV_LOG_ERROR, "could not realloc map offsets\n");
389 return err;
390 }
391 }
392 3 gxf->map_offsets[gxf->map_offsets_nb++] = pos; // do not increment here
393 }
394
395 6 gxf_write_packet_header(pb, PKT_MAP);
396
397 /* preamble */
398 6 avio_w8(pb, 0xE0); /* version */
399 6 avio_w8(pb, 0xFF); /* reserved */
400
401 6 gxf_write_material_data_section(s);
402 6 gxf_write_track_description_section(s);
403
404 6 return update_packet_size(pb, pos);
405 }
406
407 6 static int gxf_write_flt_packet(AVFormatContext *s)
408 {
409 6 GXFContext *gxf = s->priv_data;
410 6 AVIOContext *pb = s->pb;
411 6 int64_t pos = avio_tell(pb);
412 6 int fields_per_flt = (gxf->nb_fields+1) / 1000 + 1;
413 6 int flt_entries = gxf->nb_fields / fields_per_flt;
414 6 int i = 0;
415
416 6 gxf_write_packet_header(pb, PKT_FLT);
417
418 6 avio_wl32(pb, fields_per_flt); /* number of fields */
419 6 avio_wl32(pb, flt_entries); /* number of active flt entries */
420
421
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (gxf->flt_entries) {
422
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 3 times.
163 for (i = 0; i < flt_entries; i++)
423 160 avio_wl32(pb, gxf->flt_entries[(i*fields_per_flt)>>1]);
424 }
425
426 6 ffio_fill(pb, 0, (1000 - i) * 4);
427
428 6 return update_packet_size(pb, pos);
429 }
430
431 6 static int gxf_write_umf_material_description(AVFormatContext *s)
432 {
433 6 GXFContext *gxf = s->priv_data;
434 6 AVIOContext *pb = s->pb;
435
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 int timecode_base = gxf->time_base.den == 60000 ? 60 : 50;
436 6 int64_t timestamp = 0;
437 uint64_t nb_fields;
438 uint32_t timecode_in; // timecode at mark in
439 uint32_t timecode_out; // timecode at mark out
440
441 6 ff_parse_creation_time_metadata(s, &timestamp, 1);
442
443 6 timecode_in = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop,
444 gxf->tc.hh, gxf->tc.mm,
445 gxf->tc.ss, gxf->tc.ff);
446
447 6 nb_fields = gxf->nb_fields +
448 6 gxf->tc.hh * (timecode_base * 3600) +
449 6 gxf->tc.mm * (timecode_base * 60) +
450 6 gxf->tc.ss * timecode_base +
451 6 gxf->tc.ff;
452
453 6 timecode_out = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop,
454 nb_fields / (timecode_base * 3600) % 24,
455 nb_fields / (timecode_base * 60) % 60,
456 nb_fields / timecode_base % 60,
457 nb_fields % timecode_base);
458
459 6 avio_wl32(pb, gxf->flags);
460 6 avio_wl32(pb, gxf->nb_fields); /* length of the longest track */
461 6 avio_wl32(pb, gxf->nb_fields); /* length of the shortest track */
462 6 avio_wl32(pb, 0); /* mark in */
463 6 avio_wl32(pb, gxf->nb_fields); /* mark out */
464 6 avio_wl32(pb, timecode_in); /* timecode mark in */
465 6 avio_wl32(pb, timecode_out); /* timecode mark out */
466 6 avio_wl64(pb, timestamp); /* modification time */
467 6 avio_wl64(pb, timestamp); /* creation time */
468 6 avio_wl16(pb, 0); /* reserved */
469 6 avio_wl16(pb, 0); /* reserved */
470 6 avio_wl16(pb, gxf->audio_tracks);
471 6 avio_wl16(pb, 1); /* timecode track count */
472 6 avio_wl16(pb, 0); /* reserved */
473 6 avio_wl16(pb, gxf->mpeg_tracks);
474 6 return 48;
475 }
476
477 6 static int gxf_write_umf_payload(AVFormatContext *s)
478 {
479 6 GXFContext *gxf = s->priv_data;
480 6 AVIOContext *pb = s->pb;
481
482 6 avio_wl32(pb, gxf->umf_length); /* total length of the umf data */
483 6 avio_wl32(pb, 3); /* version */
484 6 avio_wl32(pb, s->nb_streams+1);
485 6 avio_wl32(pb, gxf->umf_track_offset); /* umf track section offset */
486 6 avio_wl32(pb, gxf->umf_track_size);
487 6 avio_wl32(pb, s->nb_streams+1);
488 6 avio_wl32(pb, gxf->umf_media_offset);
489 6 avio_wl32(pb, gxf->umf_media_size);
490 6 avio_wl32(pb, gxf->umf_length); /* user data offset */
491 6 avio_wl32(pb, 0); /* user data size */
492 6 avio_wl32(pb, 0); /* reserved */
493 6 avio_wl32(pb, 0); /* reserved */
494 6 return 48;
495 }
496
497 6 static int gxf_write_umf_track_description(AVFormatContext *s)
498 {
499 6 AVIOContext *pb = s->pb;
500 6 GXFContext *gxf = s->priv_data;
501 6 int64_t pos = avio_tell(pb);
502 int i;
503
504 6 gxf->umf_track_offset = pos - gxf->umf_start_offset;
505
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (i = 0; i < s->nb_streams; ++i) {
506 12 GXFStreamContext *sc = s->streams[i]->priv_data;
507 12 avio_wl16(pb, sc->media_info);
508 12 avio_wl16(pb, 1);
509 }
510
511 6 avio_wl16(pb, gxf->timecode_track.media_info);
512 6 avio_wl16(pb, 1);
513
514 6 return avio_tell(pb) - pos;
515 }
516
517 6 static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st)
518 {
519 6 GXFStreamContext *sc = st->priv_data;
520
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (st->codecpar->format == AV_PIX_FMT_YUV422P)
522 avio_wl32(pb, 2);
523 else
524 6 avio_wl32(pb, 1); /* default to 420 */
525 6 avio_wl32(pb, sc->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */
526 6 avio_wl32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */
527 6 avio_wl32(pb, 1); /* I picture per GOP */
528 6 avio_wl32(pb, sc->p_per_gop);
529 6 avio_wl32(pb, sc->b_per_i_or_p);
530
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO)
531 6 avio_wl32(pb, 2);
532 else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG1VIDEO)
533 avio_wl32(pb, 1);
534 else
535 avio_wl32(pb, 0);
536 6 avio_wl32(pb, 0); /* reserved */
537 6 return 32;
538 }
539
540 6 static int gxf_write_umf_media_timecode(AVIOContext *pb, int drop)
541 {
542 6 avio_wl32(pb, drop); /* drop frame */
543 6 ffio_fill(pb, 0, 7 * 4); /* reserved */
544 6 return 32;
545 }
546
547 static int gxf_write_umf_media_dv(AVIOContext *pb, GXFStreamContext *sc, AVStream *st)
548 {
549 int dv_umf_data = 0;
550
551 if (st->codecpar->format == AV_PIX_FMT_YUV420P)
552 dv_umf_data |= 0x20; /* marks as DVCAM instead of DVPRO */
553 avio_wl32(pb, dv_umf_data);
554 ffio_fill(pb, 0, 7 * 4);
555 return 32;
556 }
557
558 6 static int gxf_write_umf_media_audio(AVIOContext *pb, GXFStreamContext *sc)
559 {
560 6 avio_wl64(pb, av_double2int(1)); /* sound level to begin to */
561 6 avio_wl64(pb, av_double2int(1)); /* sound level to begin to */
562 6 avio_wl32(pb, 0); /* number of fields over which to ramp up sound level */
563 6 avio_wl32(pb, 0); /* number of fields over which to ramp down sound level */
564 6 avio_wl32(pb, 0); /* reserved */
565 6 avio_wl32(pb, 0); /* reserved */
566 6 return 32;
567 }
568
569 6 static int gxf_write_umf_media_description(AVFormatContext *s)
570 {
571 6 GXFContext *gxf = s->priv_data;
572 6 AVIOContext *pb = s->pb;
573 int64_t pos;
574
575 6 pos = avio_tell(pb);
576 6 gxf->umf_media_offset = pos - gxf->umf_start_offset;
577
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 for (unsigned i = 0; i <= s->nb_streams; ++i) {
578 GXFStreamContext *sc;
579 int64_t startpos, curpos;
580
581
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (i == s->nb_streams)
582 6 sc = &gxf->timecode_track;
583 else
584 12 sc = s->streams[i]->priv_data;
585
586 18 startpos = avio_tell(pb);
587 18 avio_wl16(pb, 0); /* length */
588 18 avio_wl16(pb, sc->media_info);
589 18 avio_wl16(pb, 0); /* reserved */
590 18 avio_wl16(pb, 0); /* reserved */
591 18 avio_wl32(pb, gxf->nb_fields);
592 18 avio_wl32(pb, 0); /* attributes rw, ro */
593 18 avio_wl32(pb, 0); /* mark in */
594 18 avio_wl32(pb, gxf->nb_fields); /* mark out */
595 18 avio_write(pb, ES_NAME_PATTERN, strlen(ES_NAME_PATTERN));
596 18 avio_wb16(pb, sc->media_info);
597 18 ffio_fill(pb, 0, 88 - (strlen(ES_NAME_PATTERN) + 2));
598 18 avio_wl32(pb, sc->track_type);
599 18 avio_wl32(pb, sc->sample_rate);
600 18 avio_wl32(pb, sc->sample_size);
601 18 avio_wl32(pb, 0); /* reserved */
602
603
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (sc == &gxf->timecode_track)
604 6 gxf_write_umf_media_timecode(pb, gxf->tc.drop);
605 else {
606 12 AVStream *st = s->streams[i];
607
2/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 switch (st->codecpar->codec_id) {
608 6 case AV_CODEC_ID_MPEG1VIDEO:
609 case AV_CODEC_ID_MPEG2VIDEO:
610 6 gxf_write_umf_media_mpeg(pb, st);
611 6 break;
612 6 case AV_CODEC_ID_PCM_S16LE:
613 6 gxf_write_umf_media_audio(pb, sc);
614 6 break;
615 case AV_CODEC_ID_DVVIDEO:
616 gxf_write_umf_media_dv(pb, sc, st);
617 break;
618 }
619 }
620
621 18 curpos = avio_tell(pb);
622 18 avio_seek(pb, startpos, SEEK_SET);
623 18 avio_wl16(pb, curpos - startpos);
624 18 avio_seek(pb, curpos, SEEK_SET);
625 }
626 6 return avio_tell(pb) - pos;
627 }
628
629 6 static int gxf_write_umf_packet(AVFormatContext *s)
630 {
631 6 GXFContext *gxf = s->priv_data;
632 6 AVIOContext *pb = s->pb;
633 6 int64_t pos = avio_tell(pb);
634
635 6 gxf_write_packet_header(pb, PKT_UMF);
636
637 /* preamble */
638 6 avio_w8(pb, 3); /* first and last (only) packet */
639 6 avio_wb32(pb, gxf->umf_length); /* data length */
640
641 6 gxf->umf_start_offset = avio_tell(pb);
642 6 gxf_write_umf_payload(s);
643 6 gxf_write_umf_material_description(s);
644 6 gxf->umf_track_size = gxf_write_umf_track_description(s);
645 6 gxf->umf_media_size = gxf_write_umf_media_description(s);
646 6 gxf->umf_length = avio_tell(pb) - gxf->umf_start_offset;
647 6 return update_packet_size(pb, pos);
648 }
649
650 3 static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc)
651 {
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!vsc)
653 return;
654
655
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 sc->media_type = vsc->sample_rate == 60 ? 7 : 8;
656 3 sc->sample_rate = vsc->sample_rate;
657 3 sc->media_info = ('T'<<8) | '0';
658 3 sc->track_type = 3;
659 3 sc->frame_rate_index = vsc->frame_rate_index;
660 3 sc->lines_index = vsc->lines_index;
661 3 sc->sample_size = 16;
662 3 sc->fields = vsc->fields;
663 }
664
665 2 static int gxf_init_timecode(AVFormatContext *s, GXFTimecode *tc, const char *tcstr, int fields)
666 {
667 char c;
668
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sscanf(tcstr, "%d:%d:%d%c%d", &tc->hh, &tc->mm, &tc->ss, &c, &tc->ff) != 5) {
670 av_log(s, AV_LOG_ERROR, "unable to parse timecode, "
671 "syntax: hh:mm:ss[:;.]ff\n");
672 return -1;
673 }
674
675 2 tc->color = 0;
676 2 tc->drop = c != ':';
677
678
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (fields == 2)
679 2 tc->ff = tc->ff * 2;
680
681 2 return 0;
682 }
683
684 3 static int gxf_write_header(AVFormatContext *s)
685 {
686 3 AVIOContext *pb = s->pb;
687 3 GXFContext *gxf = s->priv_data;
688 3 GXFStreamContext *vsc = NULL;
689 3 uint8_t tracks[255] = {0};
690 3 int i, media_info = 0;
691 int ret;
692 3 AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
693
694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
695 av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome\n");
696 return AVERROR_PATCHWELCOME;
697 }
698
699 3 gxf->flags |= 0x00080000; /* material is simple clip */
700
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for (i = 0; i < s->nb_streams; ++i) {
701 6 AVStream *st = s->streams[i];
702 6 GXFStreamContext *sc = av_mallocz(sizeof(*sc));
703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc)
704 return AVERROR(ENOMEM);
705 6 st->priv_data = sc;
706
707 6 sc->media_type = ff_codec_get_tag(gxf_media_types, st->codecpar->codec_id);
708
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE) {
710 av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n");
711 return AVERROR(EINVAL);
712 }
713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->sample_rate != 48000) {
714 av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n");
715 return AVERROR(EINVAL);
716 }
717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (st->codecpar->ch_layout.nb_channels != 1) {
718 av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n");
719 return AVERROR(EINVAL);
720 }
721 3 ret = ff_stream_add_bitstream_filter(st, "pcm_rechunk", "n="AV_STRINGIFY(GXF_SAMPLES_PER_FRAME));
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
723 return ret;
724 3 sc->track_type = 2;
725 3 sc->sample_rate = st->codecpar->sample_rate;
726 3 avpriv_set_pts_info(st, 64, 1, sc->sample_rate);
727 3 sc->sample_size = 16;
728 3 sc->frame_rate_index = -2;
729 3 sc->lines_index = -2;
730 3 sc->fields = -2;
731 3 gxf->audio_tracks++;
732 3 gxf->flags |= 0x04000000; /* audio is 16 bit pcm */
733 3 media_info = 'A';
734
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (i != 0) {
736 av_log(s, AV_LOG_ERROR, "video stream must be the first track\n");
737 return AVERROR(EINVAL);
738 }
739 /* FIXME check from time_base ? */
740
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if (st->codecpar->height == 480 || st->codecpar->height == 512) { /* NTSC or NTSC+VBI */
741 1 sc->frame_rate_index = 5;
742 1 sc->sample_rate = 60;
743 1 gxf->flags |= 0x00000080;
744 1 gxf->time_base = (AVRational){ 1001, 60000 };
745
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 } else if (st->codecpar->height == 576 || st->codecpar->height == 608) { /* PAL or PAL+VBI */
746 2 sc->frame_rate_index = 6;
747 2 sc->media_type++;
748 2 sc->sample_rate = 50;
749 2 gxf->flags |= 0x00000040;
750 2 gxf->time_base = (AVRational){ 1, 50 };
751 } else {
752 av_log(s, AV_LOG_ERROR, "unsupported video resolution, "
753 "gxf muxer only accepts PAL or NTSC resolutions currently\n");
754 return AVERROR(EINVAL);
755 }
756
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!tcr)
757 1 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
758 3 avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den);
759
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (gxf_find_lines_index(st) < 0)
760 sc->lines_index = -1;
761 3 sc->sample_size = st->codecpar->bit_rate;
762 3 sc->fields = 2; /* interlaced */
763
764 3 vsc = sc;
765
766
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 switch (st->codecpar->codec_id) {
767 case AV_CODEC_ID_MJPEG:
768 sc->track_type = 1;
769 gxf->flags |= 0x00004000;
770 media_info = 'J';
771 break;
772 case AV_CODEC_ID_MPEG1VIDEO:
773 sc->track_type = 9;
774 gxf->mpeg_tracks++;
775 media_info = 'L';
776 break;
777 3 case AV_CODEC_ID_MPEG2VIDEO:
778 3 sc->first_gop_closed = -1;
779 3 sc->track_type = 4;
780 3 gxf->mpeg_tracks++;
781 3 gxf->flags |= 0x00008000;
782 3 media_info = 'M';
783 3 break;
784 case AV_CODEC_ID_DVVIDEO:
785 if (st->codecpar->format == AV_PIX_FMT_YUV422P) {
786 sc->media_type += 2;
787 sc->track_type = 6;
788 gxf->flags |= 0x00002000;
789 media_info = 'E';
790 } else {
791 sc->track_type = 5;
792 gxf->flags |= 0x00001000;
793 media_info = 'D';
794 }
795 break;
796 default:
797 av_log(s, AV_LOG_ERROR, "video codec not supported\n");
798 return -1;
799 }
800 }
801 /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */
802 6 sc->media_info = media_info<<8 | ('0'+tracks[media_info]++);
803 6 sc->order = s->nb_streams - st->index;
804 }
805
806
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 if (tcr && vsc)
807 2 gxf_init_timecode(s, &gxf->tc, tcr->value, vsc->fields);
808
809 3 gxf_init_timecode_track(&gxf->timecode_track, vsc);
810 3 gxf->flags |= 0x200000; // time code track is non-drop frame
811
812
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = gxf_write_map_packet(s, 0)) < 0)
813 return ret;
814 3 gxf_write_flt_packet(s);
815 3 gxf_write_umf_packet(s);
816
817 3 gxf->packet_count = 3;
818
819 3 return 0;
820 }
821
822 3 static int gxf_write_eos_packet(AVIOContext *pb)
823 {
824 3 int64_t pos = avio_tell(pb);
825
826 3 gxf_write_packet_header(pb, PKT_EOS);
827 3 return update_packet_size(pb, pos);
828 }
829
830 3 static int gxf_write_trailer(AVFormatContext *s)
831 {
832 3 GXFContext *gxf = s->priv_data;
833 3 AVIOContext *pb = s->pb;
834 int64_t end;
835 int i;
836 int ret;
837
838 3 gxf_write_eos_packet(pb);
839 3 end = avio_tell(pb);
840 3 avio_seek(pb, 0, SEEK_SET);
841 /* overwrite map, flt and umf packets with new values */
842
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = gxf_write_map_packet(s, 1)) < 0)
843 return ret;
844 3 gxf_write_flt_packet(s);
845 3 gxf_write_umf_packet(s);
846 /* update duration in all map packets */
847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 for (i = 1; i < gxf->map_offsets_nb; i++) {
848 avio_seek(pb, gxf->map_offsets[i], SEEK_SET);
849 if ((ret = gxf_write_map_packet(s, 1)) < 0)
850 return ret;
851 }
852
853 3 avio_seek(pb, end, SEEK_SET);
854
855 3 return 0;
856 }
857
858 3 static void gxf_deinit(AVFormatContext *s)
859 {
860 3 GXFContext *gxf = s->priv_data;
861
862 3 av_freep(&gxf->flt_entries);
863 3 av_freep(&gxf->map_offsets);
864 3 }
865
866 80 static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int size)
867 {
868 80 uint32_t c=-1;
869 int i;
870
3/4
✓ Branch 0 taken 670 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 590 times.
✓ Branch 3 taken 80 times.
670 for(i=0; i<size-4 && c!=0x100; i++){
871 590 c = (c<<8) + buf[i];
872
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6 times.
590 if(c == 0x1B8 && sc->first_gop_closed == -1) /* GOP start code */
873 3 sc->first_gop_closed= (buf[i+4]>>6)&1;
874 }
875 80 return (buf[i+1]>>3)&7;
876 }
877
878 86 static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size)
879 {
880 86 GXFContext *gxf = s->priv_data;
881 86 AVIOContext *pb = s->pb;
882 86 AVStream *st = s->streams[pkt->stream_index];
883 86 GXFStreamContext *sc = st->priv_data;
884 unsigned field_nb;
885 /* If the video is frame-encoded, the frame numbers shall be represented by
886 * even field numbers.
887 * see SMPTE360M-2004 6.4.2.1.3 Media field number */
888
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 6 times.
86 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
889 80 field_nb = gxf->nb_fields;
890 } else {
891 6 field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den,
892 6 (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
893 }
894
895 86 avio_w8(pb, sc->media_type);
896 86 avio_w8(pb, st->index);
897 86 avio_wb32(pb, field_nb);
898
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 80 times.
86 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
899 6 avio_wb16(pb, 0);
900 6 avio_wb16(pb, size / 2);
901
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 } else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
902 80 int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size);
903
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 71 times.
80 if (frame_type == AV_PICTURE_TYPE_I) {
904 9 avio_w8(pb, 0x0d);
905 9 sc->iframes++;
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 } else if (frame_type == AV_PICTURE_TYPE_B) {
907 avio_w8(pb, 0x0f);
908 sc->bframes++;
909 } else {
910 71 avio_w8(pb, 0x0e);
911 71 sc->pframes++;
912 }
913 80 avio_wb24(pb, size);
914 } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
915 avio_w8(pb, size / 4096);
916 avio_wb24(pb, 0);
917 } else
918 avio_wb32(pb, size);
919 86 avio_wb32(pb, field_nb);
920 86 avio_w8(pb, 1); /* flags */
921 86 avio_w8(pb, 0); /* reserved */
922 86 return 16;
923 }
924
925 86 static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
926 {
927 86 GXFContext *gxf = s->priv_data;
928 86 AVIOContext *pb = s->pb;
929 86 AVStream *st = s->streams[pkt->stream_index];
930 86 int64_t pos = avio_tell(pb);
931 86 int padding = 0;
932 86 unsigned packet_start_offset = avio_tell(pb) / 1024;
933 int ret;
934
935 86 gxf_write_packet_header(pb, PKT_MEDIA);
936
4/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 19 times.
86 if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */
937 61 padding = 4 - pkt->size % 4;
938
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 19 times.
25 else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
939 6 padding = GXF_AUDIO_PACKET_SIZE - pkt->size;
940 86 gxf_write_media_preamble(s, pkt, pkt->size + padding);
941 86 avio_write(pb, pkt->data, pkt->size);
942 86 gxf_write_padding(pb, padding);
943
944
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 6 times.
86 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
945
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 77 times.
80 if (!(gxf->flt_entries_nb % 500)) {
946 int err;
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if ((err = av_reallocp_array(&gxf->flt_entries,
948 3 gxf->flt_entries_nb + 500,
949 sizeof(*gxf->flt_entries))) < 0) {
950 gxf->flt_entries_nb = 0;
951 gxf->nb_fields = 0;
952 av_log(s, AV_LOG_ERROR, "could not reallocate flt entries\n");
953 return err;
954 }
955 }
956 80 gxf->flt_entries[gxf->flt_entries_nb++] = packet_start_offset;
957 80 gxf->nb_fields += 2; // count fields
958 }
959
960 86 update_packet_size(pb, pos);
961
962 86 gxf->packet_count++;
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 if (gxf->packet_count == 100) {
964 if ((ret = gxf_write_map_packet(s, 0)) < 0)
965 return ret;
966 gxf->packet_count = 0;
967 }
968
969 86 return 0;
970 }
971
972 63 static int gxf_compare_field_nb(AVFormatContext *s, const AVPacket *next,
973 const AVPacket *cur)
974 {
975 63 GXFContext *gxf = s->priv_data;
976 63 const AVPacket *pkt[2] = { cur, next };
977 int i, field_nb[2];
978 GXFStreamContext *sc[2];
979
980
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 63 times.
189 for (i = 0; i < 2; i++) {
981 126 AVStream *st = s->streams[pkt[i]->stream_index];
982 126 sc[i] = st->priv_data;
983
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 63 times.
126 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
984 63 field_nb[i] = av_rescale_rnd(pkt[i]->dts, gxf->time_base.den,
985 63 (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
986 63 field_nb[i] &= ~1; // compare against even field number because audio must be before video
987 } else
988 63 field_nb[i] = pkt[i]->dts; // dts are field based
989 }
990
991
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 3 times.
123 return field_nb[1] > field_nb[0] ||
992
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
60 (field_nb[1] == field_nb[0] && sc[1]->order > sc[0]->order);
993 }
994
995 175 static int gxf_interleave_packet(AVFormatContext *s, AVPacket *pkt,
996 int flush, int has_packet)
997 {
998 int ret;
999
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 89 times.
175 if (has_packet) {
1000 86 AVStream *st = s->streams[pkt->stream_index];
1001 86 GXFStreamContext *sc = st->priv_data;
1002
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 6 times.
86 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
1003 80 pkt->pts = pkt->dts = sc->pkt_cnt * 2; // enforce 2 fields
1004 else
1005 6 pkt->pts = pkt->dts = sc->pkt_cnt * GXF_SAMPLES_PER_FRAME;
1006 86 sc->pkt_cnt++;
1007
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
86 if ((ret = ff_interleave_add_packet(s, pkt, gxf_compare_field_nb)) < 0)
1008 return ret;
1009 }
1010 175 return ff_interleave_packet_per_dts(s, pkt, flush, 0);
1011 }
1012
1013 const FFOutputFormat ff_gxf_muxer = {
1014 .p.name = "gxf",
1015 .p.long_name = NULL_IF_CONFIG_SMALL("GXF (General eXchange Format)"),
1016 .p.extensions = "gxf",
1017 .priv_data_size = sizeof(GXFContext),
1018 .p.audio_codec = AV_CODEC_ID_PCM_S16LE,
1019 .p.video_codec = AV_CODEC_ID_MPEG2VIDEO,
1020 .write_header = gxf_write_header,
1021 .write_packet = gxf_write_packet,
1022 .write_trailer = gxf_write_trailer,
1023 .deinit = gxf_deinit,
1024 .interleave_packet = gxf_interleave_packet,
1025 };
1026