aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2011-08-13 12:39:56 +0200
committerAnton Khirnov <anton@khirnov.net>2011-10-11 08:36:29 +0200
commit7ea3a78f5979f1710d91960b6ea1f0df99c94ebe (patch)
tree2cf0609f2d5902b26c4498be294ff3256125b631
parentbb611e5a6620da2883fbf0114bccd1a1628e91e3 (diff)
avconv: basic playlists input support.playlists
-rw-r--r--avconv.c116
1 files changed, 106 insertions, 10 deletions
diff --git a/avconv.c b/avconv.c
index 03c419dcb2..6c67d329d3 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1942,6 +1942,72 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb
return 0;
}
+static int playlist_advance(InputFile *ifile, OutputStream *output_streams, int nb_output_streams)
+{
+ InputStream *ist;
+ AVFormatContext *s;
+ char error[1024];
+ int ret, i, j;
+ int64_t ts_offset = 0;
+
+ /* flush/close each decoder and reset streams */
+ for (i = 0; i < ifile->nb_streams; i++) {
+ ist = &input_streams[ifile->ist_index + i];
+ if (ist->discard)
+ continue;
+ if (ist->decoding_needed) {
+ output_packet(ist, ifile->ist_index + i, output_streams, nb_output_streams, NULL);
+ avcodec_close(ist->st->codec);
+ }
+ ts_offset = FFMAX(ts_offset, ist->pts);
+ }
+ ifile->ts_offset = ts_offset;
+
+ if ((ret = av_playlist_advance(ifile->ctx, 1, NULL)) < 0) // TODO: passing options
+ return ret;
+
+ s = ifile->ctx->plist->elems[ret]->fc;
+ if ((ret = avformat_find_stream_info(s, NULL)) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "%s: could not find codec parameters\n", s->filename);
+ exit_program(1);
+ }
+
+ for (i = 0; i < ifile->nb_streams; i++) {
+ OutputStream *ost = NULL;
+ InputStream *ist = &input_streams[ifile->ist_index + i];
+
+ if (ist->discard)
+ continue;
+
+ if (i >= s->nb_streams) {
+ av_log(NULL, AV_LOG_ERROR, "Element %s in playlist %s doesn't have enough streams.\n",
+ s->filename, ifile->ctx->filename);
+ exit_program(1);
+ }
+
+ ist->st = s->streams[i];
+
+ for (j = 0; j < nb_output_streams; j++)
+ if (output_streams[j].source_index == ifile->ist_index + i) {
+ ost = &output_streams[j];
+
+ if (ost->st->codec->codec_type != s->streams[i]->codec->codec_type) {
+ av_log(NULL, AV_LOG_ERROR, "Stream %d in element %s in playlist %s has wrong type.\n",
+ i, s->filename, ifile->ctx->filename);
+ exit_program(1);
+ }
+ }
+
+ if ((ret = init_input_stream(ifile->ist_index + i, output_streams, nb_output_streams, error, sizeof(error))) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Could not initialize input stream %d in element %s: %s.\n",
+ i, s->filename, error);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int transcode_init(OutputFile *output_files,
int nb_output_files,
InputFile *input_files,
@@ -1979,6 +2045,11 @@ static int transcode_init(OutputFile *output_files,
os = output_files[ost->file_index].ctx;
ist = &input_streams[ost->source_index];
+ if (input_files[ist->file_index].ctx->plist && ost->st->stream_copy) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot streamcopy from playlist input.\n");
+ exit_program(1);
+ }
+
codec = ost->st->codec;
icodec = ist->st->codec;
@@ -2399,7 +2470,10 @@ static int transcode(OutputFile *output_files,
}
/* read a frame from it and output it in the fifo */
- is = input_files[file_index].ctx;
+ if (input_files[file_index].ctx->plist)
+ is = input_files[file_index].ctx->plist->elems[input_files[file_index].ctx->plist->cur_elem]->fc;
+ else
+ is = input_files[file_index].ctx;
ret= av_read_frame(is, &pkt);
if(ret == AVERROR(EAGAIN)){
no_packet[file_index]=1;
@@ -2407,11 +2481,16 @@ static int transcode(OutputFile *output_files,
continue;
}
if (ret < 0) {
- input_files[file_index].eof_reached = 1;
- if (opt_shortest)
- break;
- else
+ if (input_files[file_index].ctx->plist &&
+ playlist_advance(&input_files[file_index], output_streams, nb_output_streams) >= 0)
continue;
+ else {
+ input_files[file_index].eof_reached = 1;
+ if (opt_shortest)
+ break;
+ else
+ continue;
+ }
}
no_packet_count=0;
@@ -2477,7 +2556,9 @@ static int transcode(OutputFile *output_files,
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
if (ist->decoding_needed) {
- output_packet(ist, i, output_streams, nb_output_streams, NULL);
+ if (!input_files[ist->file_index].ctx->plist) {
+ output_packet(ist, i, output_streams, nb_output_streams, NULL);
+ }
}
}
flush_encoders(output_streams, nb_output_streams);
@@ -2508,7 +2589,7 @@ static int transcode(OutputFile *output_files,
/* close each decoder */
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
- if (ist->decoding_needed) {
+ if (ist->decoding_needed && !input_files[ist->file_index].ctx->plist) {
avcodec_close(ist->st->codec);
}
}
@@ -2923,17 +3004,32 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena
}
/* update the current parameters so that they match the one of the input stream */
- add_input_streams(o, ic);
+ if (ic->plist) {
+ if ((err = av_playlist_advance(ic, 1, NULL)) < 0) {
+ print_error(filename, err);
+ exit_program(1);
+ }
+ if ((ret = avformat_find_stream_info(ic->plist->elems[err]->fc, NULL)) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
+ av_close_input_file(ic);
+ exit_program(1);
+ }
+ add_input_streams(o, ic->plist->elems[0]->fc);
+ } else
+ add_input_streams(o, ic);
/* dump the file content */
av_dump_format(ic, nb_input_files, filename, 0);
input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1);
input_files[nb_input_files - 1].ctx = ic;
- input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams;
+ input_files[nb_input_files - 1].rate_emu = o->rate_emu;
input_files[nb_input_files - 1].ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
input_files[nb_input_files - 1].nb_streams = ic->nb_streams;
- input_files[nb_input_files - 1].rate_emu = o->rate_emu;
+
+ if (ic->plist)
+ input_files[nb_input_files - 1].nb_streams = ic->plist->elems[0]->fc->nb_streams;
+ input_files[nb_input_files - 1].ist_index = nb_input_streams - input_files[nb_input_files - 1].nb_streams;
for (i = 0; i < orig_nb_streams; i++)
av_dict_free(&opts[i]);