FFmpeg
Loading...
Searching...
No Matches
concatdec.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 Nicolas George
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
22#include "libavutil/avstring.h"
23#include "libavutil/avassert.h"
24#include "libavutil/bprint.h"
26#include "libavutil/mem.h"
27#include "libavutil/opt.h"
29#include "libavutil/timestamp.h"
31#include "libavcodec/bsf.h"
32#include "avformat.h"
33#include "avio_internal.h"
34#include "demux.h"
35#include "internal.h"
36#include "url.h"
37
42
47
63
64typedef struct {
65 AVClass *class;
68 unsigned nb_files;
70 int safe;
72 int eof;
74 unsigned auto_convert;
77
78static int concat_probe(const AVProbeData *probe)
79{
80 return memcmp(probe->buf, "ffconcat version 1.0", 20) ?
82}
83
84static char *get_keyword(uint8_t **cursor)
85{
86 char *ret = *cursor += strspn(*cursor, SPACE_CHARS);
87 *cursor += strcspn(*cursor, SPACE_CHARS);
88 if (**cursor) {
89 *((*cursor)++) = 0;
90 *cursor += strspn(*cursor, SPACE_CHARS);
91 }
92 return ret;
93}
94
95static int safe_filename(const char *f)
96{
97 const char *start = f;
98
99 for (; *f; f++) {
100 /* A-Za-z0-9_- */
101 if (!((unsigned)((*f | 32) - 'a') < 26 ||
102 (unsigned)(*f - '0') < 10 || *f == '_' || *f == '-')) {
103 if (f == start)
104 return 0;
105 else if (*f == '/')
106 start = f + 1;
107 else if (*f != '.')
108 return 0;
109 }
110 }
111 return 1;
112}
113
114#define FAIL(retcode) do { ret = (retcode); goto fail; } while(0)
115
116static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
117 unsigned *nb_files_alloc)
118{
120 ConcatFile *file;
121 char *url = NULL;
122 const char *proto;
123 const char *ptr;
124 size_t url_len;
125 int ret;
126
127 if (cat->safe && !safe_filename(filename)) {
128 av_log(avf, AV_LOG_ERROR, "Unsafe file name '%s'\n", filename);
129 FAIL(AVERROR(EPERM));
130 }
131
132 proto = avio_find_protocol_name(filename);
133 if (proto && av_strstart(filename, proto, &ptr) &&
134 (*ptr == ':' || *ptr == ',')) {
135 url = filename;
136 filename = NULL;
137 } else {
138 url_len = strlen(avf->url) + strlen(filename) + 16;
139 if (!(url = av_malloc(url_len)))
140 FAIL(AVERROR(ENOMEM));
141 ff_make_absolute_url(url, url_len, avf->url, filename);
142 av_freep(&filename);
143 }
144
145 if (cat->nb_files >= *nb_files_alloc) {
146 size_t n = FFMAX(*nb_files_alloc * 2, 16);
147 ConcatFile *new_files;
148 if (n <= cat->nb_files || n > SIZE_MAX / sizeof(*cat->files) ||
149 !(new_files = av_realloc(cat->files, n * sizeof(*cat->files))))
150 FAIL(AVERROR(ENOMEM));
151 cat->files = new_files;
152 *nb_files_alloc = n;
153 }
154
155 file = &cat->files[cat->nb_files++];
156 memset(file, 0, sizeof(*file));
157 *rfile = file;
158
159 file->url = url;
161 file->duration = AV_NOPTS_VALUE;
162 file->next_dts = AV_NOPTS_VALUE;
163 file->inpoint = AV_NOPTS_VALUE;
164 file->outpoint = AV_NOPTS_VALUE;
166
167 return 0;
168
169fail:
170 av_free(url);
171 av_free(filename);
172 return ret;
173}
174
175static int copy_stream_props(AVStream *st, AVStream *source_st)
176{
177 int ret;
178
179 if (st->codecpar->codec_id || !source_st->codecpar->codec_id) {
180 if (st->codecpar->extradata_size < source_st->codecpar->extradata_size) {
182 source_st->codecpar->extradata_size);
183 if (ret < 0)
184 return ret;
185 }
186 if (source_st->codecpar->extradata_size)
187 memcpy(st->codecpar->extradata, source_st->codecpar->extradata,
188 source_st->codecpar->extradata_size);
189 return 0;
190 }
191 if ((ret = avcodec_parameters_copy(st->codecpar, source_st->codecpar)) < 0)
192 return ret;
193 st->r_frame_rate = source_st->r_frame_rate;
194 st->avg_frame_rate = source_st->avg_frame_rate;
196 avpriv_set_pts_info(st, 64, source_st->time_base.num, source_st->time_base.den);
197
198 av_dict_copy(&st->metadata, source_st->metadata, 0);
199 return 0;
200}
201
203{
205 AVStream *st = cat->avf->streams[idx];
206 ConcatStream *cs = &cat->cur_file->streams[idx];
208 AVBSFContext *bsf;
209 int ret;
210
211 if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264) {
212 if (!st->codecpar->extradata_size ||
213 (st->codecpar->extradata_size >= 3 && AV_RB24(st->codecpar->extradata) == 1) ||
214 (st->codecpar->extradata_size >= 4 && AV_RB32(st->codecpar->extradata) == 1))
215 return 0;
216 av_log(cat->avf, AV_LOG_INFO,
217 "Auto-inserting h264_mp4toannexb bitstream filter\n");
218 filter = av_bsf_get_by_name("h264_mp4toannexb");
219 if (!filter) {
220 av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
221 "required for H.264 streams\n");
223 }
224 ret = av_bsf_alloc(filter, &bsf);
225 if (ret < 0)
226 return ret;
227 cs->bsf = bsf;
228
229 ret = avcodec_parameters_copy(bsf->par_in, st->codecpar);
230 if (ret < 0)
231 return ret;
232
233 ret = av_bsf_init(bsf);
234 if (ret < 0)
235 return ret;
236
238 if (ret < 0)
239 return ret;
240 }
241 return 0;
242}
243
245{
247 AVStream *st;
248 int i, ret;
249
250 for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
252 st = avf->streams[i];
253 } else {
254 if (!(st = avformat_new_stream(avf, NULL)))
255 return AVERROR(ENOMEM);
256 }
257 if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0)
258 return ret;
259 cat->cur_file->streams[i].out_stream_index = i;
260 }
261 return 0;
262}
263
265{
267 AVStream *st;
268 int i, j, ret;
269
270 for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
271 st = cat->avf->streams[i];
272 for (j = 0; j < avf->nb_streams; j++) {
273 if (avf->streams[j]->id == st->id) {
275 "Match slave stream #%d with stream #%d id 0x%x\n",
276 i, j, st->id);
277 if ((ret = copy_stream_props(avf->streams[j], st)) < 0)
278 return ret;
279 cat->cur_file->streams[i].out_stream_index = j;
280 }
281 }
282 }
283 return 0;
284}
285
287{
290 int i, ret;
291
292 if (cat->cur_file->nb_streams >= cat->avf->nb_streams)
293 return 0;
294 map = av_realloc(cat->cur_file->streams,
295 cat->avf->nb_streams * sizeof(*map));
296 if (!map)
297 return AVERROR(ENOMEM);
298 cat->cur_file->streams = map;
299 memset(map + cat->cur_file->nb_streams, 0,
300 (cat->avf->nb_streams - cat->cur_file->nb_streams) * sizeof(*map));
301
302 for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
303 map[i].out_stream_index = -1;
304 if ((ret = detect_stream_specific(avf, i)) < 0)
305 return ret;
306 }
307 switch (cat->stream_match_mode) {
308 case MATCH_ONE_TO_ONE:
309 ret = match_streams_one_to_one(avf);
310 break;
311 case MATCH_EXACT_ID:
312 ret = match_streams_exact_id(avf);
313 break;
314 default:
315 ret = AVERROR_BUG;
316 }
317 if (ret < 0)
318 return ret;
319 cat->cur_file->nb_streams = cat->avf->nb_streams;
320 return 0;
321}
322
324{
325 if (file->user_duration != AV_NOPTS_VALUE)
326 return file->user_duration;
327 if (file->outpoint != AV_NOPTS_VALUE)
328 return av_sat_sub64(file->outpoint, file->file_inpoint);
329 if (avf->duration > 0)
330 return av_sat_sub64(avf->duration, file->file_inpoint - file->file_start_time);
331 if (file->next_dts != AV_NOPTS_VALUE)
332 return file->next_dts - file->file_inpoint;
333 return AV_NOPTS_VALUE;
334}
335
336static int open_file(AVFormatContext *avf, unsigned fileno)
337{
339 ConcatFile *file = &cat->files[fileno];
341 int ret;
342
343 if (cat->avf)
345
347 if (!cat->avf)
348 return AVERROR(ENOMEM);
349
350 cat->avf->flags |= avf->flags & ~AVFMT_FLAG_CUSTOM_IO;
351 cat->avf->interrupt_callback = avf->interrupt_callback;
352
353 if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
354 return ret;
355
356 ret = av_dict_copy(&options, file->options, 0);
357 if (ret < 0)
358 return ret;
359
360 if ((ret = avformat_open_input(&cat->avf, file->url, NULL, &options)) < 0 ||
361 (ret = avformat_find_stream_info(cat->avf, NULL)) < 0) {
362 av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url);
365 return ret;
366 }
367 if (options) {
368 av_log(avf, AV_LOG_WARNING, "Unused options for '%s'.\n", file->url);
369 /* TODO log unused options once we have a proper string API */
371 }
372 cat->cur_file = file;
373 file->start_time = !fileno ? 0 :
374 cat->files[fileno - 1].start_time +
375 cat->files[fileno - 1].duration;
376 file->file_start_time = (cat->avf->start_time == AV_NOPTS_VALUE) ? 0 : cat->avf->start_time;
377 file->file_inpoint = (file->inpoint == AV_NOPTS_VALUE) ? file->file_start_time : file->inpoint;
378 file->duration = get_best_effort_duration(file, cat->avf);
379
380 if (cat->segment_time_metadata) {
381 av_dict_set_int(&file->metadata, "lavf.concatdec.start_time", file->start_time, 0);
382 if (file->duration != AV_NOPTS_VALUE)
383 av_dict_set_int(&file->metadata, "lavf.concatdec.duration", file->duration, 0);
384 }
385
386 if ((ret = match_streams(avf)) < 0)
387 return ret;
388 if (file->inpoint != AV_NOPTS_VALUE) {
389 if ((ret = avformat_seek_file(cat->avf, -1, INT64_MIN, file->inpoint, file->inpoint, 0)) < 0)
390 return ret;
391 }
392 return 0;
393}
394
396{
398 unsigned i, j;
399
400 for (i = 0; i < cat->nb_files; i++) {
401 av_freep(&cat->files[i].url);
402 for (j = 0; j < cat->files[i].nb_streams; j++) {
403 if (cat->files[i].streams[j].bsf)
404 av_bsf_free(&cat->files[i].streams[j].bsf);
405 }
406 av_freep(&cat->files[i].streams);
407 av_dict_free(&cat->files[i].metadata);
408 av_dict_free(&cat->files[i].options);
409 }
410 if (cat->avf)
412 av_freep(&cat->files);
413 return 0;
414}
415
416#define MAX_ARGS 3
417#define NEEDS_UNSAFE (1 << 0)
418#define NEEDS_FILE (1 << 1)
419#define NEEDS_STREAM (1 << 2)
420
421typedef struct ParseSyntax {
422 const char *keyword;
424 uint8_t flags;
426
443
444static const ParseSyntax syntax[] = {
445 [DIR_FFCONCAT ] = { "ffconcat", "kk", 0 },
446 [DIR_FILE ] = { "file", "s", 0 },
447 [DIR_DURATION ] = { "duration", "d", NEEDS_FILE },
448 [DIR_INPOINT ] = { "inpoint", "d", NEEDS_FILE },
449 [DIR_OUTPOINT ] = { "outpoint", "d", NEEDS_FILE },
450 [DIR_FPMETA ] = { "file_packet_meta", "ks", NEEDS_FILE },
451 [DIR_FPMETAS ] = { "file_packet_metadata", "s", NEEDS_FILE },
452 [DIR_OPTION ] = { "option", "ks", NEEDS_FILE | NEEDS_UNSAFE },
453 [DIR_STREAM ] = { "stream", "", 0 },
454 [DIR_EXSID ] = { "exact_stream_id", "i", NEEDS_STREAM },
455 [DIR_STMETA ] = { "stream_meta", "ks", NEEDS_STREAM },
456 [DIR_STCODEC ] = { "stream_codec", "k", NEEDS_STREAM },
457 [DIR_STEDATA ] = { "stream_extradata", "k", NEEDS_STREAM },
458 [DIR_CHAPTER ] = { "chapter", "idd", 0 },
459};
460
462{
464 unsigned nb_files_alloc = 0;
465 AVBPrint bp;
466 uint8_t *cursor, *keyword;
467 ConcatFile *file = NULL;
468 AVStream *stream = NULL;
469 AVChapter *chapter = NULL;
470 unsigned line = 0, arg;
471 const ParseSyntax *dir;
472 char *arg_kw[MAX_ARGS];
473 char *arg_str[MAX_ARGS] = { 0 };
474 int64_t arg_int[MAX_ARGS];
475 int ret;
476
478
479 while ((ret = ff_read_line_to_bprint_overwrite(avf->pb, &bp)) >= 0) {
480 line++;
481 cursor = bp.str;
482 keyword = get_keyword(&cursor);
483 if (!*keyword || *keyword == '#')
484 continue;
485 for (dir = syntax; dir < syntax + FF_ARRAY_ELEMS(syntax); dir++)
486 if (!strcmp(dir->keyword, keyword))
487 break;
488 if (dir >= syntax + FF_ARRAY_ELEMS(syntax)) {
489 av_log(avf, AV_LOG_ERROR, "Line %d: unknown keyword '%s'\n",
490 line, keyword);
492 }
493
494 /* Flags check */
495 if ((dir->flags & NEEDS_UNSAFE) && cat->safe) {
496 av_log(avf, AV_LOG_ERROR, "Line %d: %s not allowed if safe\n", line, keyword);
498 }
499 if ((dir->flags & NEEDS_FILE) && !cat->nb_files) {
500 av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n", line, keyword);
502 }
503 if ((dir->flags & NEEDS_STREAM) && !avf->nb_streams) {
504 av_log(avf, AV_LOG_ERROR, "Line %d: %s without stream\n", line, keyword);
506 }
507
508 /* Arguments parsing */
509 for (arg = 0; arg < FF_ARRAY_ELEMS(dir->args) && dir->args[arg]; arg++) {
510 switch (dir->args[arg]) {
511 case 'd': /* duration */
512 arg_kw[arg] = get_keyword(&cursor);
513 ret = av_parse_time(&arg_int[arg], arg_kw[arg], 1);
514 if (ret < 0) {
515 av_log(avf, AV_LOG_ERROR, "Line %d: invalid duration '%s'\n",
516 line, arg_kw[arg]);
517 goto fail;
518 }
519 break;
520 case 'i': /* integer */
521 arg_int[arg] = strtol(get_keyword(&cursor), NULL, 0);
522 break;
523 case 'k': /* keyword */
524 arg_kw[arg] = get_keyword(&cursor);
525 break;
526 case 's': /* string */
527 av_assert0(!arg_str[arg]);
528 arg_str[arg] = av_get_token((const char **)&cursor, SPACE_CHARS);
529 if (!arg_str[arg])
530 FAIL(AVERROR(ENOMEM));
531 if (!*arg_str[arg]) {
532 av_log(avf, AV_LOG_ERROR, "Line %d: string required\n", line);
534 }
535 break;
536 default:
538 }
539 }
540
541 /* Directive action */
542 switch ((ParseDirective)(dir - syntax)) {
543
544 case DIR_FFCONCAT:
545 if (strcmp(arg_kw[0], "version") || strcmp(arg_kw[1], "1.0")) {
546 av_log(avf, AV_LOG_ERROR, "Line %d: invalid version\n", line);
548 }
549 break;
550
551 case DIR_FILE:
552 ret = add_file(avf, arg_str[0], &file, &nb_files_alloc);
553 arg_str[0] = NULL;
554 if (ret < 0)
555 goto fail;
556 break;
557
558 case DIR_DURATION:
559 file->user_duration = arg_int[0];
560 break;
561
562 case DIR_INPOINT:
563 file->inpoint = arg_int[0];
564 break;
565
566 case DIR_OUTPOINT:
567 file->outpoint = arg_int[0];
568 break;
569
570 case DIR_FPMETA:
571 ret = av_dict_set(&file->metadata, arg_kw[0], arg_str[1], AV_DICT_DONT_STRDUP_VAL);
572 arg_str[1] = NULL;
573 if (ret < 0)
574 FAIL(ret);
575 break;
576
577 case DIR_FPMETAS:
578 if ((ret = av_dict_parse_string(&file->metadata, arg_str[0], "=", "", 0)) < 0) {
579 av_log(avf, AV_LOG_ERROR, "Line %d: failed to parse metadata string\n", line);
581 }
583 "'file_packet_metadata key=value:key=value' is deprecated, "
584 "use multiple 'file_packet_meta key value' instead\n");
585 av_freep(&arg_str[0]);
586 break;
587
588 case DIR_OPTION:
589 ret = av_dict_set(&file->options, arg_kw[0], arg_str[1], AV_DICT_DONT_STRDUP_VAL);
590 arg_str[1] = NULL;
591 if (ret < 0)
592 FAIL(ret);
593 break;
594
595 case DIR_STREAM:
596 stream = avformat_new_stream(avf, NULL);
597 if (!stream)
598 FAIL(AVERROR(ENOMEM));
599 break;
600
601 case DIR_EXSID:
602 stream->id = arg_int[0];
603 break;
604 case DIR_STMETA:
605 ret = av_dict_set(&stream->metadata, arg_kw[0], arg_str[1], AV_DICT_DONT_STRDUP_VAL);
606 arg_str[1] = NULL;
607 if (ret < 0)
608 FAIL(ret);
609 break;
610
611 case DIR_STCODEC: {
612 const AVCodecDescriptor *codec = avcodec_descriptor_get_by_name(arg_kw[0]);
613 if (!codec) {
614 av_log(avf, AV_LOG_ERROR, "Line %d: codec '%s' not found\n", line, arg_kw[0]);
616 }
617 stream->codecpar->codec_type = codec->type;
618 stream->codecpar->codec_id = codec->id;
619 break;
620 }
621
622 case DIR_STEDATA: {
623 int size = ff_hex_to_data(NULL, arg_kw[0]);
624 ret = ff_alloc_extradata(stream->codecpar, size);
625 if (ret < 0)
626 FAIL(ret);
627 ff_hex_to_data(stream->codecpar->extradata, arg_kw[0]);
628 break;
629 }
630
631 case DIR_CHAPTER:
632 chapter = avpriv_new_chapter(avf, arg_int[0], AV_TIME_BASE_Q,
633 arg_int[1], arg_int[2], NULL);
634 if (!chapter)
635 FAIL(ENOMEM);
636 break;
637
638 default:
640 }
641 }
642
643 if (!file) {
645 goto fail;
646 }
647
648 if (file->inpoint != AV_NOPTS_VALUE && file->outpoint != AV_NOPTS_VALUE) {
649 if (file->inpoint > file->outpoint ||
650 file->outpoint - (uint64_t)file->inpoint > INT64_MAX)
652 }
653
654fail:
655 for (arg = 0; arg < MAX_ARGS; arg++)
656 av_freep(&arg_str[arg]);
658 return ret == AVERROR_EOF ? 0 : ret;
659}
660
662{
664 int64_t time = 0;
665 unsigned i;
666 int ret;
667
668 ret = concat_parse_script(avf);
669 if (ret < 0)
670 return ret;
671 if (!cat->nb_files) {
672 av_log(avf, AV_LOG_ERROR, "No files to concat\n");
673 return AVERROR_INVALIDDATA;
674 }
675
676 for (i = 0; i < cat->nb_files; i++) {
677 if (cat->files[i].start_time == AV_NOPTS_VALUE)
678 cat->files[i].start_time = time;
679 else
680 time = cat->files[i].start_time;
681 if (cat->files[i].user_duration == AV_NOPTS_VALUE) {
682 if (cat->files[i].inpoint == AV_NOPTS_VALUE || cat->files[i].outpoint == AV_NOPTS_VALUE ||
683 cat->files[i].outpoint - (uint64_t)cat->files[i].inpoint != av_sat_sub64(cat->files[i].outpoint, cat->files[i].inpoint)
684 )
685 break;
686 cat->files[i].user_duration = cat->files[i].outpoint - cat->files[i].inpoint;
687 }
688 cat->files[i].duration = cat->files[i].user_duration;
689 if (time + (uint64_t)cat->files[i].user_duration > INT64_MAX)
690 return AVERROR_INVALIDDATA;
691 time += cat->files[i].user_duration;
692 }
693 if (i == cat->nb_files) {
694 avf->duration = time;
695 cat->seekable = 1;
696 }
697
698 cat->stream_match_mode = avf->nb_streams ? MATCH_EXACT_ID :
700 if ((ret = open_file(avf, 0)) < 0)
701 return ret;
702
703 return 0;
704}
705
707{
709 unsigned fileno = cat->cur_file - cat->files;
710
711 cat->cur_file->duration = get_best_effort_duration(cat->cur_file, cat->avf);
712
713 if (++fileno >= cat->nb_files) {
714 cat->eof = 1;
715 return AVERROR_EOF;
716 }
717 return open_file(avf, fileno);
718}
719
721{
722 int ret;
723
724 if (cs->bsf) {
725 ret = av_bsf_send_packet(cs->bsf, pkt);
726 if (ret < 0) {
727 av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
728 "failed to send input packet\n");
729 return ret;
730 }
731
732 while (!ret)
733 ret = av_bsf_receive_packet(cs->bsf, pkt);
734
735 if (ret < 0 && (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)) {
736 av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
737 "failed to receive output packet\n");
738 return ret;
739 }
740 }
741 return 0;
742}
743
744/* Returns true if the packet dts is greater or equal to the specified outpoint. */
746{
747 if (cat->cur_file->outpoint != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE) {
748 return av_compare_ts(pkt->dts, cat->avf->streams[pkt->stream_index]->time_base,
749 cat->cur_file->outpoint, AV_TIME_BASE_Q) >= 0;
750 }
751 return 0;
752}
753
755{
757 int ret;
759 ConcatStream *cs;
760 AVStream *st;
761 FFStream *sti;
762
763 if (cat->eof)
764 return AVERROR_EOF;
765
766 if (!cat->avf)
767 return AVERROR(EIO);
768
769 while (1) {
770 ret = av_read_frame(cat->avf, pkt);
771 if (ret == AVERROR_EOF) {
772 if ((ret = open_next_file(avf)) < 0)
773 return ret;
774 continue;
775 }
776 if (ret < 0)
777 return ret;
778 if ((ret = match_streams(avf)) < 0) {
779 return ret;
780 }
783 if ((ret = open_next_file(avf)) < 0)
784 return ret;
785 continue;
786 }
787 cs = &cat->cur_file->streams[pkt->stream_index];
788 if (cs->out_stream_index < 0) {
790 continue;
791 }
792 break;
793 }
794 if ((ret = filter_packet(avf, cs, pkt)) < 0)
795 return ret;
796
797 st = cat->avf->streams[pkt->stream_index];
798 sti = ffstream(st);
799 av_log(avf, AV_LOG_DEBUG, "file:%d stream:%d pts:%s pts_time:%s dts:%s dts_time:%s",
800 (unsigned)(cat->cur_file - cat->files), pkt->stream_index,
801 av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
802 av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
803
804 delta = av_rescale_q(cat->cur_file->start_time - cat->cur_file->file_inpoint,
806 cat->avf->streams[pkt->stream_index]->time_base);
807 if (pkt->pts != AV_NOPTS_VALUE)
808 pkt->pts += delta;
809 if (pkt->dts != AV_NOPTS_VALUE)
810 pkt->dts += delta;
811 av_log(avf, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
812 av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
813 av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
814 if (cat->cur_file->metadata) {
815 size_t metadata_len;
816 char* packed_metadata = av_packet_pack_dictionary(cat->cur_file->metadata, &metadata_len);
817 if (!packed_metadata)
818 return AVERROR(ENOMEM);
820 packed_metadata, metadata_len);
821 if (ret < 0) {
822 av_freep(&packed_metadata);
823 return ret;
824 }
825 }
826
827 if (cat->cur_file->duration == AV_NOPTS_VALUE && sti->cur_dts != AV_NOPTS_VALUE) {
828 int64_t next_dts = av_rescale_q(sti->cur_dts, st->time_base, AV_TIME_BASE_Q);
829 if (cat->cur_file->next_dts == AV_NOPTS_VALUE || next_dts > cat->cur_file->next_dts) {
830 cat->cur_file->next_dts = next_dts;
831 }
832 }
833
834 pkt->stream_index = cs->out_stream_index;
835 return 0;
836}
837
838static int try_seek(AVFormatContext *avf, int stream,
839 int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
840{
842 int64_t t0 = cat->cur_file->start_time - cat->cur_file->file_inpoint;
843
844 ts -= t0;
845 min_ts = min_ts == INT64_MIN ? INT64_MIN : min_ts - t0;
846 max_ts = max_ts == INT64_MAX ? INT64_MAX : max_ts - t0;
847 if (stream >= 0) {
848 if (stream >= cat->avf->nb_streams)
849 return AVERROR(EIO);
850 ff_rescale_interval(AV_TIME_BASE_Q, cat->avf->streams[stream]->time_base,
851 &min_ts, &ts, &max_ts);
852 }
853 return avformat_seek_file(cat->avf, stream, min_ts, ts, max_ts, flags);
854}
855
856static int real_seek(AVFormatContext *avf, int stream,
857 int64_t min_ts, int64_t ts, int64_t max_ts, int flags, AVFormatContext *cur_avf)
858{
860 int ret, left, right;
861
862 if (stream >= 0) {
863 if (stream >= avf->nb_streams)
864 return AVERROR(EINVAL);
866 &min_ts, &ts, &max_ts);
867 }
868
869 left = 0;
870 right = cat->nb_files;
871
872 /* Always support seek to start */
873 if (ts <= 0)
874 right = 1;
875 else if (!cat->seekable)
876 return AVERROR(ESPIPE); /* XXX: can we use it? */
877
878 while (right - left > 1) {
879 int mid = (left + right) / 2;
880 if (ts < cat->files[mid].start_time)
881 right = mid;
882 else
883 left = mid;
884 }
885
886 if (cat->cur_file != &cat->files[left]) {
887 if ((ret = open_file(avf, left)) < 0)
888 return ret;
889 } else {
890 cat->avf = cur_avf;
891 }
892
893 ret = try_seek(avf, stream, min_ts, ts, max_ts, flags);
894 if (ret < 0 &&
895 left < cat->nb_files - 1 &&
896 cat->files[left + 1].start_time < max_ts) {
897 if (cat->cur_file == &cat->files[left])
898 cat->avf = NULL;
899 if ((ret = open_file(avf, left + 1)) < 0)
900 return ret;
901 ret = try_seek(avf, stream, min_ts, ts, max_ts, flags);
902 }
903 return ret;
904}
905
906static int concat_seek(AVFormatContext *avf, int stream,
907 int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
908{
910 ConcatFile *cur_file_saved = cat->cur_file;
911 AVFormatContext *cur_avf_saved = cat->avf;
912 int ret;
913
915 return AVERROR(ENOSYS);
916 cat->avf = NULL;
917 if ((ret = real_seek(avf, stream, min_ts, ts, max_ts, flags, cur_avf_saved)) < 0) {
918 if (cat->cur_file != cur_file_saved) {
919 if (cat->avf)
921 }
922 cat->avf = cur_avf_saved;
923 cat->cur_file = cur_file_saved;
924 } else {
925 if (cat->cur_file != cur_file_saved) {
926 avformat_close_input(&cur_avf_saved);
927 }
928 cat->eof = 0;
929 }
930 return ret;
931}
932
933#define OFFSET(x) offsetof(ConcatContext, x)
934#define DEC AV_OPT_FLAG_DECODING_PARAM
935
936static const AVOption options[] = {
937 { "safe", "enable safe mode",
938 OFFSET(safe), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC },
939 { "auto_convert", "automatically convert bitstream format",
940 OFFSET(auto_convert), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC },
941 { "segment_time_metadata", "output file segment start time and duration as packet metadata",
942 OFFSET(segment_time_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
943 { NULL }
944};
945
946static const AVClass concat_class = {
947 .class_name = "concat demuxer",
948 .item_name = av_default_item_name,
949 .option = options,
950 .version = LIBAVUTIL_VERSION_INT,
951};
952
953
955 .p.name = "concat",
956 .p.long_name = NULL_IF_CONFIG_SMALL("Virtual concatenation script"),
957 .p.priv_class = &concat_class,
958 .priv_data_size = sizeof(ConcatContext),
959 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
964 .read_seek2 = concat_seek,
965};
static int probe(const AVProbeData *p)
Definition act.c:39
const FFInputFormat ff_concat_demuxer
Definition concatdec.c:954
#define attribute_nonstring
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition avformat.c:879
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVPROBE_SCORE_MAX
maximum score
Definition avformat.h:483
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition avformat.h:2617
#define AVSEEK_FLAG_FRAME
seeking based on frame number
Definition avformat.h:2619
#define AVFMT_FLAG_CUSTOM_IO
The caller has supplied a custom AVIOContext, don't avio_close() it.
Definition avformat.h:1492
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition avio.c:725
int64_t ff_read_line_to_bprint_overwrite(AVIOContext *s, struct AVBPrint *bp)
Read a whole line of text from AVIOContext to an AVBPrint buffer overwriting its contents.
Definition aviobuf.c:858
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:69
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
static int read_probe(const AVProbeData *p)
Definition cdg.c:30
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Definition codec_par.c:107
#define av_sat_sub64
Definition common.h:142
static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
Definition concat.c:168
static int concat_read_header(AVFormatContext *avf)
Definition concatdec.c:661
#define NEEDS_FILE
Definition concatdec.c:418
static int match_streams(AVFormatContext *avf)
Definition concatdec.c:286
static int safe_filename(const char *f)
Definition concatdec.c:95
static const ParseSyntax syntax[]
Definition concatdec.c:444
static char * get_keyword(uint8_t **cursor)
Definition concatdec.c:84
#define MAX_ARGS
Definition concatdec.c:416
static int concat_probe(const AVProbeData *probe)
Definition concatdec.c:78
#define NEEDS_STREAM
Definition concatdec.c:419
ParseDirective
Definition concatdec.c:427
@ DIR_FPMETA
Definition concatdec.c:433
@ DIR_STCODEC
Definition concatdec.c:439
@ DIR_INPOINT
Definition concatdec.c:431
@ DIR_FPMETAS
Definition concatdec.c:434
@ DIR_STMETA
Definition concatdec.c:438
@ DIR_OUTPOINT
Definition concatdec.c:432
@ DIR_EXSID
Definition concatdec.c:437
@ DIR_FFCONCAT
Definition concatdec.c:428
@ DIR_STREAM
Definition concatdec.c:436
@ DIR_OPTION
Definition concatdec.c:435
@ DIR_STEDATA
Definition concatdec.c:440
@ DIR_DURATION
Definition concatdec.c:430
@ DIR_FILE
Definition concatdec.c:429
@ DIR_CHAPTER
Definition concatdec.c:441
static int copy_stream_props(AVStream *st, AVStream *source_st)
Definition concatdec.c:175
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
Definition concatdec.c:754
static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile, unsigned *nb_files_alloc)
Definition concatdec.c:116
static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt)
Definition concatdec.c:745
static const AVClass concat_class
Definition concatdec.c:946
static int try_seek(AVFormatContext *avf, int stream, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Definition concatdec.c:838
static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
Definition concatdec.c:720
#define NEEDS_UNSAFE
Definition concatdec.c:417
static int open_next_file(AVFormatContext *avf)
Definition concatdec.c:706
#define FAIL(retcode)
Definition concatdec.c:114
static int concat_seek(AVFormatContext *avf, int stream, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Definition concatdec.c:906
static int match_streams_exact_id(AVFormatContext *avf)
Definition concatdec.c:264
static int concat_read_close(AVFormatContext *avf)
Definition concatdec.c:395
static int concat_parse_script(AVFormatContext *avf)
Definition concatdec.c:461
#define OFFSET(x)
Definition concatdec.c:933
static int open_file(AVFormatContext *avf, unsigned fileno)
Definition concatdec.c:336
static int real_seek(AVFormatContext *avf, int stream, int64_t min_ts, int64_t ts, int64_t max_ts, int flags, AVFormatContext *cur_avf)
Definition concatdec.c:856
static int detect_stream_specific(AVFormatContext *avf, int idx)
Definition concatdec.c:202
static int64_t get_best_effort_duration(ConcatFile *file, AVFormatContext *avf)
Definition concatdec.c:323
static int match_streams_one_to_one(AVFormatContext *avf)
Definition concatdec.c:244
ConcatMatchMode
Definition concatdec.c:38
@ MATCH_EXACT_ID
Definition concatdec.c:40
@ MATCH_ONE_TO_ONE
Definition concatdec.c:39
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
AVChapter * avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, int64_t start, int64_t end, const char *title)
Add a new chapter.
Definition demux_utils.c:43
void ff_rescale_interval(AVRational tb_in, AVRational tb_out, int64_t *min_ts, int64_t *ts, int64_t *max_ts)
Rescales a timestamp and the endpoints of an interval to which the temstamp belongs,...
Definition seek.c:752
#define FF_INFMT_FLAG_INIT_CLEANUP
For an FFInputFormat with this flag set read_close() needs to be called by the caller upon read_heade...
Definition demux.h:35
static AVPacket * pkt
#define SPACE_CHARS
static int safe_filename(const char *f, int allow_subdir)
static int64_t start_time
Definition ffplay.c:329
static unsigned int nb_streams
Definition ffprobe.c:352
static int read_header(FFV1Context *f, RangeCoder *c)
Definition ffv1dec.c:578
#define fail
Definition test.h:479
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
void av_bsf_free(AVBSFContext **pctx)
Free a bitstream filter context and everything associated with it; write NULL into the supplied point...
Definition bsf.c:47
int av_bsf_init(AVBSFContext *ctx)
Prepare the filter for use, after all the parameters and options have been set.
Definition bsf.c:147
int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
Allocate a context for a given bitstream filter.
Definition bsf.c:99
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
Retrieve a filtered packet.
Definition bsf.c:228
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
Submit a packet for filtering.
Definition bsf.c:200
const AVBitStreamFilter * av_bsf_get_by_name(const char *name)
const AVCodecDescriptor * avcodec_descriptor_get_by_name(const char *name)
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_PKT_DATA_STRINGS_METADATA
A list of zero terminated key/value strings.
Definition packet.h:169
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
uint8_t * av_packet_pack_dictionary(const AVDictionary *dict, size_t *size)
Pack a dictionary for use in side_data.
Definition packet.c:319
int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, uint8_t *data, size_t size)
Wrap an existing array as a packet side data.
Definition packet.c:197
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition options.c:165
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition seek.c:664
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition demux.c:1588
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition demux.c:231
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition demux.c:2606
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition demux.c:377
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:235
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition dict.c:247
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
Definition dict.h:79
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:210
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:177
#define AVERROR_DECODER_NOT_FOUND
Decoder not found.
Definition error.h:54
#define AVERROR_BSF_NOT_FOUND
Bitstream filter not found.
Definition error.h:51
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition avstring.c:143
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
const VDPAUPixFmtMap * map
#define AV_RB32(p)
#define AV_RB24(x)
const char * arg
Definition jacosubdec.c:65
int ff_hex_to_data(uint8_t *data, const char *p)
Parse a string of hexadecimal strings.
Definition utils.c:485
static av_always_inline FFStream * ffstream(AVStream *st)
Definition internal.h:365
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0.
Definition utils.c:237
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static av_cold int read_close(AVFormatContext *ctx)
Definition libcdio.c:143
#define DEC
Definition librsvgdec.c:149
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define av_realloc(p, s)
Definition ops_static.c:54
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition parseutils.c:592
misc parsing utilities
#define FF_ARRAY_ELEMS(a)
The bitstream filter state.
Definition bsf.h:68
AVCodecParameters * par_in
Parameters of the input stream.
Definition bsf.h:90
AVCodecParameters * par_out
Parameters of the output stream.
Definition bsf.h:96
Describe the class of an AVClass context structure.
Definition log.h:76
This struct describes the properties of a single codec described by an AVCodecID.
Definition codec_desc.h:38
enum AVCodecID id
Definition codec_desc.h:39
enum AVMediaType type
Definition codec_desc.h:40
int extradata_size
Size of the extradata content in bytes.
Definition codec_par.h:75
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition codec_par.h:71
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
Format I/O context.
Definition avformat.h:1333
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition avformat.h:1389
AVIOContext * pb
I/O context.
Definition avformat.h:1375
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1484
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition avformat.h:1618
char * url
input or output URL.
Definition avformat.h:1449
void * priv_data
Format private data.
Definition avformat.h:1361
AVStream ** streams
A list of all streams in the file.
Definition avformat.h:1401
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition avformat.h:1468
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
This structure contains the data a format has to probe a file.
Definition avformat.h:471
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition avformat.h:844
AVDictionary * metadata
Definition avformat.h:846
int id
Format-specific stream ID.
Definition avformat.h:778
AVRational avg_frame_rate
Average framerate.
Definition avformat.h:855
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:805
AVRational r_frame_rate
Real base framerate of the stream.
Definition avformat.h:900
ConcatFile * cur_file
Definition concatdec.c:67
ConcatMatchMode stream_match_mode
Definition concatdec.c:73
ConcatFile * files
Definition concatdec.c:66
unsigned nb_files
Definition concatdec.c:68
int segment_time_metadata
Definition concatdec.c:75
AVFormatContext * avf
Definition concatdec.c:69
unsigned auto_convert
Definition concatdec.c:74
int64_t file_start_time
Definition concatdec.c:51
int64_t outpoint
Definition concatdec.c:58
char * url
Definition concatdec.c:49
int64_t next_dts
Definition concatdec.c:55
int64_t user_duration
Definition concatdec.c:54
int64_t inpoint
Definition concatdec.c:57
ConcatStream * streams
Definition concatdec.c:56
AVDictionary * metadata
Definition concatdec.c:59
int64_t duration
Definition concatdec.c:53
int64_t start_time
Definition concatdec.c:50
int64_t file_inpoint
Definition concatdec.c:52
AVDictionary * options
Definition concatdec.c:60
int nb_streams
Definition concatdec.c:61
AVBSFContext * bsf
Definition concatdec.c:44
int out_stream_index
Definition concatdec.c:45
int64_t cur_dts
Definition internal.h:360
const char * keyword
Definition concatdec.c:422
uint8_t flags
Definition concatdec.c:424
attribute_nonstring char args[MAX_ARGS]
Definition concatdec.c:423
#define av_free(p)
#define av_freep(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
timestamp utils, mostly useful for debugging/logging purposes
#define av_ts2str(ts)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition timestamp.h:54
#define av_ts2timestr(ts, tb)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition timestamp.h:83
int size
int ff_make_absolute_url(char *buf, int size, const char *base, const char *rel)
Convert a relative url into an absolute url, given a base url.
Definition url.c:321
unbuffered private I/O API
float delta
#define cat(a, bpp, b)
Definition vp9dsp_init.h:32