From 7ea3a78f5979f1710d91960b6ea1f0df99c94ebe Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 Aug 2011 12:39:56 +0200 Subject: avconv: basic playlists input support. --- avconv.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file 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]); -- cgit v1.2.3