static uint8_t *audio_out;
static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
-static void *samples;
-
#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
typedef struct InputStream {
int discard; /* true if stream data should be discarded */
int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */
AVCodec *dec;
+ AVFrame *decoded_frame;
+ AVFrame *filtered_frame;
int64_t start; /* time when read started */
int64_t next_pts; /* synthetic pts for cases where pkt.pts
av_dict_free(&output_files[i].opts);
}
for(i=0;i<nb_input_files;i++) {
- av_close_input_file(input_files[i].ctx);
+ avformat_close_input(&input_files[i].ctx);
}
- for (i = 0; i < nb_input_streams; i++)
+ for (i = 0; i < nb_input_streams; i++) {
+ av_freep(&input_streams[i].decoded_frame);
+ av_freep(&input_streams[i].filtered_frame);
av_dict_free(&input_streams[i].opts);
+ }
if (vstats_file)
fclose(vstats_file);
av_free(audio_buf);
av_free(audio_out);
allocated_audio_buf_size= allocated_audio_out_size= 0;
- av_free(samples);
#if CONFIG_AVFILTER
avfilter_uninit();
exit (255);
}
- exit(ret); /* not all OS-es handle main() return value */
+ exit(ret);
}
static void assert_avoptions(AVDictionary *m)
memset(buf, fill_char, size);
}
-static void do_audio_out(AVFormatContext *s,
- OutputStream *ost,
- InputStream *ist,
- unsigned char *buf, int size)
+static void do_audio_out(AVFormatContext *s, OutputStream *ost,
+ InputStream *ist, AVFrame *decoded_frame)
{
uint8_t *buftmp;
int64_t audio_out_size, audio_buf_size;
- int64_t allocated_for_size= size;
int size_out, frame_bytes, ret, resample_changed;
AVCodecContext *enc= ost->st->codec;
int osize = av_get_bytes_per_sample(enc->sample_fmt);
int isize = av_get_bytes_per_sample(dec->sample_fmt);
const int coded_bps = av_get_bits_per_sample(enc->codec->id);
+ uint8_t *buf = decoded_frame->data[0];
+ int size = decoded_frame->nb_samples * dec->channels * isize;
+ int64_t allocated_for_size = size;
need_realloc:
audio_buf_size= (allocated_for_size + isize*dec->channels - 1) / (isize*dec->channels);
static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
{
- static unsigned int samples_size = 0;
+ AVFrame *decoded_frame;
+ AVCodecContext *avctx = ist->st->codec;
int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
- uint8_t *decoded_data_buf = NULL;
- int decoded_data_size = 0;
int i, ret;
- if (pkt && samples_size < FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE)) {
- av_free(samples);
- samples_size = FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE);
- samples = av_malloc(samples_size);
- }
- decoded_data_size = samples_size;
+ if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
+ return AVERROR(ENOMEM);
+ else
+ avcodec_get_frame_defaults(ist->decoded_frame);
+ decoded_frame = ist->decoded_frame;
- ret = avcodec_decode_audio3(ist->st->codec, samples, &decoded_data_size,
- pkt);
- if (ret < 0)
+ ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
+ if (ret < 0) {
return ret;
- *got_output = decoded_data_size > 0;
+ }
- /* Some bug in mpeg audio decoder gives */
- /* decoded_data_size < 0, it seems they are overflows */
if (!*got_output) {
/* no audio frame */
return ret;
}
- decoded_data_buf = (uint8_t *)samples;
- ist->next_pts += ((int64_t)AV_TIME_BASE/bps * decoded_data_size) /
- (ist->st->codec->sample_rate * ist->st->codec->channels);
+ /* if the decoder provides a pts, use it instead of the last packet pts.
+ the decoder could be delaying output by a packet or more. */
+ if (decoded_frame->pts != AV_NOPTS_VALUE)
+ ist->next_pts = decoded_frame->pts;
+
+ /* increment next_pts to use for the case where the input stream does not
+ have timestamps or there are multiple frames in the packet */
+ ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
+ avctx->sample_rate;
// preprocess audio (volume)
if (audio_volume != 256) {
- switch (ist->st->codec->sample_fmt) {
+ int decoded_data_size = decoded_frame->nb_samples * avctx->channels * bps;
+ void *samples = decoded_frame->data[0];
+ switch (avctx->sample_fmt) {
case AV_SAMPLE_FMT_U8:
{
uint8_t *volp = samples;
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
- do_audio_out(output_files[ost->file_index].ctx, ost, ist,
- decoded_data_buf, decoded_data_size);
+ do_audio_out(output_files[ost->file_index].ctx, ost, ist, decoded_frame);
}
+
return ret;
}
int frame_available = 1;
#endif
- if (!(decoded_frame = avcodec_alloc_frame()))
+ if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
return AVERROR(ENOMEM);
+ else
+ avcodec_get_frame_defaults(ist->decoded_frame);
+ decoded_frame = ist->decoded_frame;
pkt->pts = *pkt_pts;
pkt->dts = ist->pts;
*pkt_pts = AV_NOPTS_VALUE;
ret = avcodec_decode_video2(ist->st->codec,
decoded_frame, got_output, pkt);
if (ret < 0)
- goto fail;
+ return ret;
quality = same_quant ? decoded_frame->quality : 0;
if (!*got_output) {
/* no picture yet */
- av_freep(&decoded_frame);
return ret;
}
ist->next_pts = ist->pts = decoded_frame->best_effort_timestamp;
decoded_frame->pts = ist->pts;
av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
- if (!(filtered_frame = avcodec_alloc_frame())) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
+ if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
+ av_free(buffer_to_free);
+ return AVERROR(ENOMEM);
+ } else
+ avcodec_get_frame_defaults(ist->filtered_frame);
+ filtered_frame = ist->filtered_frame;
frame_available = avfilter_poll_frame(ost->output_video_filter->inputs[0]);
}
while (frame_available) {
if (ost->picref)
avfilter_unref_buffer(ost->picref);
}
- av_freep(&filtered_frame);
#endif
}
-fail:
av_free(buffer_to_free);
- av_freep(&decoded_frame);
return ret;
}
ic->flags |= AVFMT_FLAG_NONBLOCK;
ic->interrupt_callback = int_cb;
- /* open the input file with generic libav function */
+ /* open the input file with generic avformat function */
err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
if (err < 0) {
print_error(filename, err);
ret = avformat_find_stream_info(ic, opts);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
- av_close_input_file(ic);
+ avformat_close_input(&ic);
exit_program(1);
}
return 0;
}
-static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
-{
- int i, err;
- AVFormatContext *ic = avformat_alloc_context();
-
- ic->interrupt_callback = int_cb;
- err = avformat_open_input(&ic, filename, NULL, NULL);
- if (err < 0)
- return err;
- /* copy stream format */
- for(i=0;i<ic->nb_streams;i++) {
- AVStream *st;
- OutputStream *ost;
- AVCodec *codec;
-
- codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
- ost = new_output_stream(o, s, codec->type);
- st = ost->st;
-
- // FIXME: a more elegant solution is needed
- memcpy(st, ic->streams[i], sizeof(AVStream));
- st->info = av_malloc(sizeof(*st->info));
- memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
- avcodec_copy_context(st->codec, ic->streams[i]->codec);
-
- if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
- choose_sample_fmt(st, codec);
- else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
- choose_pixel_fmt(st, codec);
- }
-
- av_close_input_file(ic);
- return 0;
-}
-
static void opt_output_file(void *optctx, const char *filename)
{
OptionsContext *o = optctx;
file_oformat= oc->oformat;
oc->interrupt_callback = int_cb;
- if (!strcmp(file_oformat->name, "ffm") &&
- av_strstart(filename, "http:", NULL)) {
- /* special case for files sent to ffserver: we get the stream
- parameters from ffserver */
- int err = read_ffserver_streams(o, oc, filename);
- if (err < 0) {
- print_error(filename, err);
- exit_program(1);
- }
- } else if (!o->nb_stream_maps) {
+ if (!o->nb_stream_maps) {
/* pick the "best" stream of each type */
#define NEW_STREAM(type, index)\
if (index >= 0) {\
}
if (!(oc->oformat->flags & AVFMT_NOFILE)) {
- /* test if it already exists to avoid loosing precious files */
+ /* test if it already exists to avoid losing precious files */
assert_file_overwrite(filename);
/* open the file */
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
{ "codec", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
{ "pre", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(presets)}, "preset name", "preset" },
- { "map", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map}, "set input stream mapping", "file.stream[:syncfile.syncstream]" },
+ { "map", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map}, "set input stream mapping", "[-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]]" },
{ "map_metadata", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map_metadata}, "set metadata information of outfile from infile",
"outfile[,metadata]:infile[,metadata]" },
{ "map_chapters", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(chapters_input_file)}, "set chapters mapping", "input_file_index" },