]> git.sesse.net Git - ffmpeg/blob - libavformat/tee.c
avformat/msf: Also check the codec tag in probing
[ffmpeg] / libavformat / tee.c
1 /*
2  * Tee pseudo-muxer
3  * Copyright (c) 2012 Nicolas George
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 License
9  * 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
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with FFmpeg; if not, write to the Free Software * Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22
23 #include "libavutil/avutil.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/opt.h"
26 #include "internal.h"
27 #include "avformat.h"
28 #include "avio_internal.h"
29
30 #define MAX_SLAVES 16
31
32 typedef struct {
33     AVFormatContext *avf;
34     AVBitStreamFilterContext **bsfs; ///< bitstream filters per stream
35
36     /** map from input to output streams indexes,
37      * disabled output streams are set to -1 */
38     int *stream_map;
39 } TeeSlave;
40
41 typedef struct TeeContext {
42     const AVClass *class;
43     unsigned nb_slaves;
44     TeeSlave slaves[MAX_SLAVES];
45 } TeeContext;
46
47 static const char *const slave_delim     = "|";
48 static const char *const slave_opt_open  = "[";
49 static const char *const slave_opt_close = "]";
50 static const char *const slave_opt_delim = ":]"; /* must have the close too */
51 static const char *const slave_bsfs_spec_sep = "/";
52 static const char *const slave_select_sep = ",";
53
54 static const AVClass tee_muxer_class = {
55     .class_name = "Tee muxer",
56     .item_name  = av_default_item_name,
57     .version    = LIBAVUTIL_VERSION_INT,
58 };
59
60 static int parse_slave_options(void *log, char *slave,
61                                AVDictionary **options, char **filename)
62 {
63     const char *p;
64     char *key, *val;
65     int ret;
66
67     if (!strspn(slave, slave_opt_open)) {
68         *filename = slave;
69         return 0;
70     }
71     p = slave + 1;
72     if (strspn(p, slave_opt_close)) {
73         *filename = (char *)p + 1;
74         return 0;
75     }
76     while (1) {
77         ret = av_opt_get_key_value(&p, "=", slave_opt_delim, 0, &key, &val);
78         if (ret < 0) {
79             av_log(log, AV_LOG_ERROR, "No option found near \"%s\"\n", p);
80             goto fail;
81         }
82         ret = av_dict_set(options, key, val,
83                           AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
84         if (ret < 0)
85             goto fail;
86         if (strspn(p, slave_opt_close))
87             break;
88         p++;
89     }
90     *filename = (char *)p + 1;
91     return 0;
92
93 fail:
94     av_dict_free(options);
95     return ret;
96 }
97
98 /**
99  * Parse list of bitstream filters and add them to the list of filters
100  * pointed to by bsfs.
101  *
102  * The list must be specified in the form:
103  * BSFS ::= BSF[,BSFS]
104  */
105 static int parse_bsfs(void *log_ctx, const char *bsfs_spec,
106                       AVBitStreamFilterContext **bsfs)
107 {
108     char *bsf_name, *buf, *dup, *saveptr;
109     int ret = 0;
110
111     if (!(dup = buf = av_strdup(bsfs_spec)))
112         return AVERROR(ENOMEM);
113
114     while (bsf_name = av_strtok(buf, ",", &saveptr)) {
115         AVBitStreamFilterContext *bsf = av_bitstream_filter_init(bsf_name);
116
117         if (!bsf) {
118             av_log(log_ctx, AV_LOG_ERROR,
119                    "Cannot initialize bitstream filter with name '%s', "
120                    "unknown filter or internal error happened\n",
121                    bsf_name);
122             ret = AVERROR_UNKNOWN;
123             goto end;
124         }
125
126         /* append bsf context to the list of bsf contexts */
127         *bsfs = bsf;
128         bsfs = &bsf->next;
129
130         buf = NULL;
131     }
132
133 end:
134     av_free(dup);
135     return ret;
136 }
137
138 static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
139 {
140     int i, ret;
141     AVDictionary *options = NULL;
142     AVDictionaryEntry *entry;
143     char *filename;
144     char *format = NULL, *select = NULL;
145     AVFormatContext *avf2 = NULL;
146     AVStream *st, *st2;
147     int stream_count;
148     int fullret;
149     char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL;
150
151     if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0)
152         return ret;
153
154 #define STEAL_OPTION(option, field) do {                                \
155         if ((entry = av_dict_get(options, option, NULL, 0))) {          \
156             field = entry->value;                                       \
157             entry->value = NULL; /* prevent it from being freed */      \
158             av_dict_set(&options, option, NULL, 0);                     \
159         }                                                               \
160     } while (0)
161
162     STEAL_OPTION("f", format);
163     STEAL_OPTION("select", select);
164
165     ret = avformat_alloc_output_context2(&avf2, NULL, format, filename);
166     if (ret < 0)
167         goto end;
168     av_dict_copy(&avf2->metadata, avf->metadata, 0);
169     avf2->opaque   = avf->opaque;
170     avf2->io_open  = avf->io_open;
171     avf2->io_close = avf->io_close;
172
173     tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map));
174     if (!tee_slave->stream_map) {
175         ret = AVERROR(ENOMEM);
176         goto end;
177     }
178
179     stream_count = 0;
180     for (i = 0; i < avf->nb_streams; i++) {
181         st = avf->streams[i];
182         if (select) {
183             tmp_select = av_strdup(select);  // av_strtok is destructive so we regenerate it in each loop
184             if (!tmp_select) {
185                 ret = AVERROR(ENOMEM);
186                 goto end;
187             }
188             fullret = 0;
189             first_subselect = tmp_select;
190             next_subselect = NULL;
191             while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) {
192                 first_subselect = NULL;
193
194                 ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect);
195                 if (ret < 0) {
196                     av_log(avf, AV_LOG_ERROR,
197                            "Invalid stream specifier '%s' for output '%s'\n",
198                            subselect, slave);
199                     goto end;
200                 }
201                 if (ret != 0) {
202                     fullret = 1; // match
203                     break;
204                 }
205             }
206             av_freep(&tmp_select);
207
208             if (fullret == 0) { /* no match */
209                 tee_slave->stream_map[i] = -1;
210                 continue;
211             }
212         }
213         tee_slave->stream_map[i] = stream_count++;
214
215         if (!(st2 = avformat_new_stream(avf2, NULL))) {
216             ret = AVERROR(ENOMEM);
217             goto end;
218         }
219         st2->id = st->id;
220         st2->r_frame_rate        = st->r_frame_rate;
221         st2->time_base           = st->time_base;
222         st2->start_time          = st->start_time;
223         st2->duration            = st->duration;
224         st2->nb_frames           = st->nb_frames;
225         st2->disposition         = st->disposition;
226         st2->sample_aspect_ratio = st->sample_aspect_ratio;
227         st2->avg_frame_rate      = st->avg_frame_rate;
228         av_dict_copy(&st2->metadata, st->metadata, 0);
229         if ((ret = avcodec_copy_context(st2->codec, st->codec)) < 0)
230             goto end;
231     }
232
233     if (!(avf2->oformat->flags & AVFMT_NOFILE)) {
234         if ((ret = avf2->io_open(avf2, &avf2->pb, filename, AVIO_FLAG_WRITE, NULL)) < 0) {
235             av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n",
236                    slave, av_err2str(ret));
237             goto end;
238         }
239     }
240
241     if ((ret = avformat_write_header(avf2, &options)) < 0) {
242         av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n",
243                slave, av_err2str(ret));
244         goto end;
245     }
246
247     tee_slave->avf = avf2;
248     tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(TeeSlave));
249     if (!tee_slave->bsfs) {
250         ret = AVERROR(ENOMEM);
251         goto end;
252     }
253
254     entry = NULL;
255     while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) {
256         const char *spec = entry->key + strlen("bsfs");
257         if (*spec) {
258             if (strspn(spec, slave_bsfs_spec_sep) != 1) {
259                 av_log(avf, AV_LOG_ERROR,
260                        "Specifier separator in '%s' is '%c', but only characters '%s' "
261                        "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep);
262                 return AVERROR(EINVAL);
263             }
264             spec++; /* consume separator */
265         }
266
267         for (i = 0; i < avf2->nb_streams; i++) {
268             ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec);
269             if (ret < 0) {
270                 av_log(avf, AV_LOG_ERROR,
271                        "Invalid stream specifier '%s' in bsfs option '%s' for slave "
272                        "output '%s'\n", spec, entry->key, filename);
273                 goto end;
274             }
275
276             if (ret > 0) {
277                 av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave "
278                        "output '%s'\n", spec, entry->value, i, filename);
279                 if (tee_slave->bsfs[i]) {
280                     av_log(avf, AV_LOG_WARNING,
281                            "Duplicate bsfs specification associated to stream %d of slave "
282                            "output '%s', filters will be ignored\n", i, filename);
283                     continue;
284                 }
285                 ret = parse_bsfs(avf, entry->value, &tee_slave->bsfs[i]);
286                 if (ret < 0) {
287                     av_log(avf, AV_LOG_ERROR,
288                            "Error parsing bitstream filter sequence '%s' associated to "
289                            "stream %d of slave output '%s'\n", entry->value, i, filename);
290                     goto end;
291                 }
292             }
293         }
294
295         av_dict_set(&options, entry->key, NULL, 0);
296     }
297
298     if (options) {
299         entry = NULL;
300         while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX)))
301             av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key);
302         ret = AVERROR_OPTION_NOT_FOUND;
303         goto end;
304     }
305
306 end:
307     av_free(format);
308     av_free(select);
309     av_dict_free(&options);
310     av_freep(&tmp_select);
311     return ret;
312 }
313
314 static void close_slaves(AVFormatContext *avf)
315 {
316     TeeContext *tee = avf->priv_data;
317     AVFormatContext *avf2;
318     unsigned i, j;
319
320     for (i = 0; i < tee->nb_slaves; i++) {
321         avf2 = tee->slaves[i].avf;
322
323         for (j = 0; j < avf2->nb_streams; j++) {
324             AVBitStreamFilterContext *bsf_next, *bsf = tee->slaves[i].bsfs[j];
325             while (bsf) {
326                 bsf_next = bsf->next;
327                 av_bitstream_filter_close(bsf);
328                 bsf = bsf_next;
329             }
330         }
331         av_freep(&tee->slaves[i].stream_map);
332         av_freep(&tee->slaves[i].bsfs);
333
334         ff_format_io_close(avf2, &avf2->pb);
335         avformat_free_context(avf2);
336         tee->slaves[i].avf = NULL;
337     }
338 }
339
340 static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
341 {
342     int i;
343     av_log(log_ctx, log_level, "filename:'%s' format:%s\n",
344            slave->avf->filename, slave->avf->oformat->name);
345     for (i = 0; i < slave->avf->nb_streams; i++) {
346         AVStream *st = slave->avf->streams[i];
347         AVBitStreamFilterContext *bsf = slave->bsfs[i];
348
349         av_log(log_ctx, log_level, "    stream:%d codec:%s type:%s",
350                i, avcodec_get_name(st->codec->codec_id),
351                av_get_media_type_string(st->codec->codec_type));
352         if (bsf) {
353             av_log(log_ctx, log_level, " bsfs:");
354             while (bsf) {
355                 av_log(log_ctx, log_level, "%s%s",
356                        bsf->filter->name, bsf->next ? "," : "");
357                 bsf = bsf->next;
358             }
359         }
360         av_log(log_ctx, log_level, "\n");
361     }
362 }
363
364 static int tee_write_header(AVFormatContext *avf)
365 {
366     TeeContext *tee = avf->priv_data;
367     unsigned nb_slaves = 0, i;
368     const char *filename = avf->filename;
369     char *slaves[MAX_SLAVES];
370     int ret;
371
372     while (*filename) {
373         if (nb_slaves == MAX_SLAVES) {
374             av_log(avf, AV_LOG_ERROR, "Maximum %d slave muxers reached.\n",
375                    MAX_SLAVES);
376             ret = AVERROR_PATCHWELCOME;
377             goto fail;
378         }
379         if (!(slaves[nb_slaves++] = av_get_token(&filename, slave_delim))) {
380             ret = AVERROR(ENOMEM);
381             goto fail;
382         }
383         if (strspn(filename, slave_delim))
384             filename++;
385     }
386
387     for (i = 0; i < nb_slaves; i++) {
388         if ((ret = open_slave(avf, slaves[i], &tee->slaves[i])) < 0)
389             goto fail;
390         log_slave(&tee->slaves[i], avf, AV_LOG_VERBOSE);
391         av_freep(&slaves[i]);
392     }
393
394     tee->nb_slaves = nb_slaves;
395
396     for (i = 0; i < avf->nb_streams; i++) {
397         int j, mapped = 0;
398         for (j = 0; j < tee->nb_slaves; j++)
399             mapped += tee->slaves[j].stream_map[i] >= 0;
400         if (!mapped)
401             av_log(avf, AV_LOG_WARNING, "Input stream #%d is not mapped "
402                    "to any slave.\n", i);
403     }
404     return 0;
405
406 fail:
407     for (i = 0; i < nb_slaves; i++)
408         av_freep(&slaves[i]);
409     close_slaves(avf);
410     return ret;
411 }
412
413 static int tee_write_trailer(AVFormatContext *avf)
414 {
415     TeeContext *tee = avf->priv_data;
416     AVFormatContext *avf2;
417     int ret_all = 0, ret;
418     unsigned i;
419
420     for (i = 0; i < tee->nb_slaves; i++) {
421         avf2 = tee->slaves[i].avf;
422         if ((ret = av_write_trailer(avf2)) < 0)
423             if (!ret_all)
424                 ret_all = ret;
425         if (!(avf2->oformat->flags & AVFMT_NOFILE))
426             ff_format_io_close(avf2, &avf2->pb);
427     }
428     close_slaves(avf);
429     return ret_all;
430 }
431
432 static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
433 {
434     TeeContext *tee = avf->priv_data;
435     AVFormatContext *avf2;
436     AVPacket pkt2;
437     int ret_all = 0, ret;
438     unsigned i, s;
439     int s2;
440     AVRational tb, tb2;
441
442     for (i = 0; i < tee->nb_slaves; i++) {
443         avf2 = tee->slaves[i].avf;
444         s = pkt->stream_index;
445         s2 = tee->slaves[i].stream_map[s];
446         if (s2 < 0)
447             continue;
448
449         if ((ret = av_copy_packet(&pkt2, pkt)) < 0 ||
450             (ret = av_dup_packet(&pkt2))< 0)
451             if (!ret_all) {
452                 ret_all = ret;
453                 continue;
454             }
455         tb  = avf ->streams[s ]->time_base;
456         tb2 = avf2->streams[s2]->time_base;
457         pkt2.pts      = av_rescale_q(pkt->pts,      tb, tb2);
458         pkt2.dts      = av_rescale_q(pkt->dts,      tb, tb2);
459         pkt2.duration = av_rescale_q(pkt->duration, tb, tb2);
460         pkt2.stream_index = s2;
461
462         if ((ret = av_apply_bitstream_filters(avf2->streams[s2]->codec, &pkt2,
463                                               tee->slaves[i].bsfs[s2])) < 0 ||
464             (ret = av_interleaved_write_frame(avf2, &pkt2)) < 0)
465             if (!ret_all)
466                 ret_all = ret;
467     }
468     return ret_all;
469 }
470
471 AVOutputFormat ff_tee_muxer = {
472     .name              = "tee",
473     .long_name         = NULL_IF_CONFIG_SMALL("Multiple muxer tee"),
474     .priv_data_size    = sizeof(TeeContext),
475     .write_header      = tee_write_header,
476     .write_trailer     = tee_write_trailer,
477     .write_packet      = tee_write_packet,
478     .priv_class        = &tee_muxer_class,
479     .flags             = AVFMT_NOFILE,
480 };