diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
| commit | f7813a5324be39d13ab536c245d15dfc602a7849 (patch) | |
| tree | fad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/ffmpeg.c | |
| parent | b7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff) | |
basic type mechanism working
Diffstat (limited to 'ffmpeg/ffmpeg.c')
| -rw-r--r-- | ffmpeg/ffmpeg.c | 542 |
1 files changed, 363 insertions, 179 deletions
diff --git a/ffmpeg/ffmpeg.c b/ffmpeg/ffmpeg.c index 12c7a28..5ccbf10 100644 --- a/ffmpeg/ffmpeg.c +++ b/ffmpeg/ffmpeg.c @@ -30,6 +30,8 @@ #include <stdlib.h> #include <errno.h> #include <limits.h> +#include <stdint.h> + #if HAVE_ISATTY #if HAVE_IO_H #include <io.h> @@ -38,15 +40,14 @@ #include <unistd.h> #endif #endif + #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" -#include "libswscale/swscale.h" #include "libswresample/swresample.h" #include "libavutil/opt.h" #include "libavutil/channel_layout.h" #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" -#include "libavutil/colorspace.h" #include "libavutil/fifo.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" @@ -64,7 +65,6 @@ # include "libavfilter/avcodec.h" # include "libavfilter/avfilter.h" -# include "libavfilter/avfiltergraph.h" # include "libavfilter/buffersrc.h" # include "libavfilter/buffersink.h" @@ -129,6 +129,7 @@ static int64_t subtitle_size = 0; static int64_t extra_size = 0; static int nb_frames_dup = 0; static int nb_frames_drop = 0; +static int64_t decode_error_stat[2]; static int current_time; AVIOContext *progress_avio = NULL; @@ -162,6 +163,8 @@ static struct termios oldtty; static int restore_tty; #endif +static void free_input_threads(void); + /* sub2video hack: Convert subtitles to video with alpha to insert them in filter graphs. @@ -318,7 +321,7 @@ sigterm_handler(int sig) received_nb_signals++; term_exit(); if(received_nb_signals > 3) - exit(123); + exit_program(123); } void term_init(void) @@ -333,7 +336,6 @@ void term_init(void) if (istty && tcgetattr (0, &tty) == 0) { oldtty = tty; restore_tty = 1; - atexit(term_exit); tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); @@ -421,7 +423,7 @@ static int decode_interrupt_cb(void *ctx) const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; -static void exit_program(void) +static void ffmpeg_cleanup(int ret) { int i, j; @@ -442,6 +444,7 @@ static void exit_program(void) av_freep(&filtergraphs[i]->outputs[j]); } av_freep(&filtergraphs[i]->outputs); + av_freep(&filtergraphs[i]->graph_desc); av_freep(&filtergraphs[i]); } av_freep(&filtergraphs); @@ -451,7 +454,7 @@ static void exit_program(void) /* close files */ for (i = 0; i < nb_output_files; i++) { AVFormatContext *s = output_files[i]->ctx; - if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_close(s->pb); avformat_free_context(s); av_dict_free(&output_files[i]->opts); @@ -465,7 +468,9 @@ static void exit_program(void) bsfc = next; } output_streams[i]->bitstream_filters = NULL; - avcodec_free_frame(&output_streams[i]->filtered_frame); + av_frame_free(&output_streams[i]->filtered_frame); + + av_parser_close(output_streams[i]->parser); av_freep(&output_streams[i]->forced_keyframes); av_expr_free(output_streams[i]->forced_keyframes_pexpr); @@ -473,6 +478,9 @@ static void exit_program(void) av_freep(&output_streams[i]->logfile_prefix); av_freep(&output_streams[i]); } +#if HAVE_PTHREADS + free_input_threads(); +#endif for (i = 0; i < nb_input_files; i++) { avformat_close_input(&input_files[i]->ctx); av_freep(&input_files[i]); @@ -484,6 +492,7 @@ static void exit_program(void) avsubtitle_free(&input_streams[i]->prev_sub.subtitle); av_frame_free(&input_streams[i]->sub2video.frame); av_freep(&input_streams[i]->filters); + av_freep(&input_streams[i]->hwaccel_device); av_freep(&input_streams[i]); } @@ -498,13 +507,13 @@ static void exit_program(void) uninit_opts(); - avfilter_uninit(); avformat_network_deinit(); if (received_sigterm) { av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n", (int) received_sigterm); } + term_exit(); } void assert_avoptions(AVDictionary *m) @@ -512,13 +521,13 @@ void assert_avoptions(AVDictionary *m) AVDictionaryEntry *t; if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key); - exit(1); + exit_program(1); } } static void abort_codec_experimental(AVCodec *c, int encoder) { - exit(1); + exit_program(1); } static void update_benchmark(const char *fmt, ...) @@ -548,17 +557,6 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) pkt->pts = pkt->dts = AV_NOPTS_VALUE; - if ((avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) && pkt->dts != AV_NOPTS_VALUE) { - int64_t max = ost->st->cur_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); - if (ost->st->cur_dts && ost->st->cur_dts != AV_NOPTS_VALUE && max > pkt->dts) { - av_log(s, max - pkt->dts > 2 || avctx->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG, - "st:%d PTS: %"PRId64" DTS: %"PRId64" < %"PRId64" invalid, clipping\n", pkt->stream_index, pkt->pts, pkt->dts, max); - if(pkt->pts >= pkt->dts) - pkt->pts = FFMAX(pkt->pts, max); - pkt->dts = max; - } - } - /* * Audio encoders may split the packets -- #frames in != #packets out. * But there is no reordering, so we can limit the number of output packets @@ -596,20 +594,44 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, av_buffer_default_free, NULL, 0); if (!new_pkt.buf) - exit(1); + exit_program(1); } else if (a < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s", bsfc->filter->name, pkt->stream_index, avctx->codec ? avctx->codec->name : "copy"); print_error("", a); if (exit_on_error) - exit(1); + exit_program(1); } *pkt = new_pkt; bsfc = bsfc->next; } + if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS) && + (avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) && + pkt->dts != AV_NOPTS_VALUE && + ost->last_mux_dts != AV_NOPTS_VALUE) { + int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); + if (pkt->dts < max) { + int loglevel = max - pkt->dts > 2 || avctx->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; + av_log(s, loglevel, "Non-monotonous DTS in output stream " + "%d:%d; previous: %"PRId64", current: %"PRId64"; ", + ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); + if (exit_on_error) { + av_log(NULL, AV_LOG_FATAL, "aborting.\n"); + exit_program(1); + } + av_log(s, loglevel, "changing to %"PRId64". This may result " + "in incorrect timestamps in the output file.\n", + max); + if(pkt->pts >= pkt->dts) + pkt->pts = FFMAX(pkt->pts, max); + pkt->dts = max; + } + } + ost->last_mux_dts = pkt->dts; + pkt->stream_index = ost->index; if (debug_ts) { @@ -625,7 +647,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { print_error("av_interleaved_write_frame()", ret); - exit(1); + exit_program(1); } } @@ -675,7 +697,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, update_benchmark(NULL); if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) { av_log(NULL, AV_LOG_FATAL, "Audio encoding failed (avcodec_encode_audio2)\n"); - exit(1); + exit_program(1); } update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); @@ -701,49 +723,6 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, } } -#if FF_API_DEINTERLACE -static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void **bufp) -{ - AVCodecContext *dec; - AVPicture *picture2; - AVPicture picture_tmp; - uint8_t *buf = 0; - - dec = ist->st->codec; - - /* deinterlace : must be done before any resize */ - if (FF_API_DEINTERLACE && do_deinterlace) { - int size; - - /* create temporary picture */ - size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height); - if (size < 0) - return; - buf = av_malloc(size); - if (!buf) - return; - - picture2 = &picture_tmp; - avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height); - - if (avpicture_deinterlace(picture2, picture, - dec->pix_fmt, dec->width, dec->height) < 0) { - /* if error, do not deinterlace */ - av_log(NULL, AV_LOG_WARNING, "Deinterlacing failed\n"); - av_free(buf); - buf = NULL; - picture2 = picture; - } - } else { - picture2 = picture; - } - - if (picture != picture2) - *picture = *picture2; - *bufp = buf; -} -#endif - static void do_subtitle_out(AVFormatContext *s, OutputStream *ost, InputStream *ist, @@ -758,7 +737,7 @@ static void do_subtitle_out(AVFormatContext *s, if (sub->pts == AV_NOPTS_VALUE) { av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); if (exit_on_error) - exit(1); + exit_program(1); return; } @@ -777,7 +756,9 @@ static void do_subtitle_out(AVFormatContext *s, nb = 1; /* shift timestamp to honor -ss and make check_recording_time() work with -t */ - pts = sub->pts - output_files[ost->file_index]->start_time; + pts = sub->pts; + if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE) + pts -= output_files[ost->file_index]->start_time; for (i = 0; i < nb; i++) { ost->sync_opts = av_rescale_q(pts, AV_TIME_BASE_Q, enc->time_base); if (!check_recording_time(ost)) @@ -794,7 +775,7 @@ static void do_subtitle_out(AVFormatContext *s, subtitle_out_max_size, sub); if (subtitle_out_size < 0) { av_log(NULL, AV_LOG_FATAL, "Subtitle encoding failed\n"); - exit(1); + exit_program(1); } av_init_packet(&pkt); @@ -841,10 +822,29 @@ static void do_video_out(AVFormatContext *s, nb_frames = 1; format_video_sync = video_sync_method; - if (format_video_sync == VSYNC_AUTO) - format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; + if (format_video_sync == VSYNC_AUTO) { + if(!strcmp(s->oformat->name, "avi")) { + format_video_sync = VSYNC_VFR; + } else + format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; + if ( ist + && format_video_sync == VSYNC_CFR + && input_files[ist->file_index]->ctx->nb_streams == 1 + && input_files[ist->file_index]->input_ts_offset == 0) { + format_video_sync = VSYNC_VSCFR; + } + if (format_video_sync == VSYNC_CFR && copy_ts) { + format_video_sync = VSYNC_VSCFR; + } + } switch (format_video_sync) { + case VSYNC_VSCFR: + if (ost->frame_number == 0 && delta - duration >= 0.5) { + av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta - duration)); + delta = duration; + ost->sync_opts = lrint(sync_ipts); + } case VSYNC_CFR: // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (delta < -1.1) @@ -889,7 +889,11 @@ static void do_video_out(AVFormatContext *s, in_picture->pts = ost->sync_opts; +#if 1 if (!check_recording_time(ost)) +#else + if (ost->frame_number >= ost->max_frames) +#endif return; if (s->oformat->flags & AVFMT_RAWPICTURE && @@ -969,7 +973,7 @@ static void do_video_out(AVFormatContext *s, update_benchmark("encode_video %d.%d", ost->file_index, ost->index); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); - exit(1); + exit_program(1); } if (got_packet) { @@ -1006,10 +1010,10 @@ static void do_video_out(AVFormatContext *s, * flush, we need to limit them here, before they go into encoder. */ ost->frame_number++; - } if (vstats_filename && frame_size) do_video_stats(ost, frame_size); + } } static double psnr(double d) @@ -1028,7 +1032,7 @@ static void do_video_stats(OutputStream *ost, int frame_size) vstats_file = fopen(vstats_filename, "w"); if (!vstats_file) { perror("fopen"); - exit(1); + exit_program(1); } } @@ -1074,10 +1078,9 @@ static int reap_filters(void) if (!ost->filter) continue; - if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) { + if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { return AVERROR(ENOMEM); - } else - avcodec_get_frame_defaults(ost->filtered_frame); + } filtered_frame = ost->filtered_frame; while (1) { @@ -1085,26 +1088,20 @@ static int reap_filters(void) AV_BUFFERSINK_FLAG_NO_REQUEST); if (ret < 0) { if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { - char buf[256]; - av_strerror(ret, buf, sizeof(buf)); av_log(NULL, AV_LOG_WARNING, - "Error in av_buffersink_get_buffer_ref(): %s\n", buf); + "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); } break; } frame_pts = AV_NOPTS_VALUE; if (filtered_frame->pts != AV_NOPTS_VALUE) { + int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; filtered_frame->pts = frame_pts = av_rescale_q(filtered_frame->pts, ost->filter->filter->inputs[0]->time_base, ost->st->codec->time_base) - - av_rescale_q(of->start_time, + av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->codec->time_base); - - if (of->start_time && filtered_frame->pts < 0) { - av_frame_unref(filtered_frame); - continue; - } } //if (ost->source_index >= 0) // *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold @@ -1113,7 +1110,7 @@ static int reap_filters(void) switch (ost->filter->filter->inputs[0]->type) { case AVMEDIA_TYPE_VIDEO: filtered_frame->pts = frame_pts; - if (!ost->frame_aspect_ratio) + if (!ost->frame_aspect_ratio.num) ost->st->codec->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; do_video_out(of->ctx, ost, filtered_frame); @@ -1367,7 +1364,7 @@ static void flush_encoders(void) update_benchmark("flush %s %d.%d", desc, ost->file_index, ost->index); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s encoding failed\n", desc); - exit(1); + exit_program(1); } *size += pkt.size; if (ost->logfile && enc->stats_out) { @@ -1406,7 +1403,7 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) if (ost->source_index != ist_index) return 0; - if (of->start_time && ist->pts < of->start_time) + if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time) return 0; return 1; @@ -1415,7 +1412,10 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; - int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); + InputFile *f = input_files [ist->file_index]; + int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); + int64_t ist_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ist->st->time_base); AVPicture pict; AVPacket opkt; @@ -1425,16 +1425,32 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p !ost->copy_initial_nonkeyframes) return; - if (!ost->frame_number && ist->pts < of->start_time && - !ost->copy_prior_start) - return; + if (pkt->pts == AV_NOPTS_VALUE) { + if (!ost->frame_number && ist->pts < start_time && + !ost->copy_prior_start) + return; + } else { + if (!ost->frame_number && pkt->pts < ist_tb_start_time && + !ost->copy_prior_start) + return; + } if (of->recording_time != INT64_MAX && - ist->pts >= of->recording_time + of->start_time) { + ist->pts >= of->recording_time + start_time) { close_output_stream(ost); return; } + if (f->recording_time != INT64_MAX) { + start_time = f->ctx->start_time; + if (f->start_time != AV_NOPTS_VALUE) + start_time += f->start_time; + if (ist->pts >= f->recording_time + start_time) { + close_output_stream(ost); + return; + } + } + /* force the input stream PTS */ if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_size += pkt->size; @@ -1474,15 +1490,19 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO && ost->st->codec->codec_id != AV_CODEC_ID_VC1 ) { - if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) { + if (av_parser_change(ost->parser, ost->st->codec, + &opkt.data, &opkt.size, + pkt->data, pkt->size, + pkt->flags & AV_PKT_FLAG_KEY)) { opkt.buf = av_buffer_create(opkt.data, opkt.size, av_buffer_default_free, NULL, 0); if (!opkt.buf) - exit(1); + exit_program(1); } } else { opkt.data = pkt->data; opkt.size = pkt->size; } + av_copy_packet_side_data(&opkt, pkt); if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (of->ctx->oformat->flags & AVFMT_RAWPICTURE)) { /* store AVPicture in AVPacket, as expected by the output format */ @@ -1496,16 +1516,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p ost->st->codec->frame_number++; } -static void rate_emu_sleep(InputStream *ist) -{ - if (input_files[ist->file_index]->rate_emu) { - int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); - int64_t now = av_gettime() - ist->start; - if (pts > now) - av_usleep(pts - now); - } -} - int guess_input_channel_layout(InputStream *ist) { AVCodecContext *dec = ist->st->codec; @@ -1533,7 +1543,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) int i, ret, err = 0, resample_changed; AVRational decoded_frame_tb; - if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame())) + if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) return AVERROR(ENOMEM); if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) return AVERROR(ENOMEM); @@ -1548,6 +1558,9 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) ret = AVERROR_INVALIDDATA; } + if (*got_output || ret<0 || pkt->size) + decode_error_stat[ret<0] ++; + if (!*got_output || ret < 0) { if (!pkt->size) { for (i = 0; i < ist->nb_filters; i++) @@ -1569,8 +1582,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) avctx->sample_rate; #endif - rate_emu_sleep(ist); - resample_changed = ist->resample_sample_fmt != decoded_frame->format || ist->resample_channels != avctx->channels || ist->resample_channel_layout != decoded_frame->channel_layout || @@ -1582,7 +1593,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) av_log(NULL, AV_LOG_FATAL, "Unable to find default channel " "layout for Input Stream #%d.%d\n", ist->file_index, ist->st->index); - exit(1); + exit_program(1); } decoded_frame->channel_layout = avctx->channel_layout; @@ -1610,7 +1621,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) int j; if (configure_filtergraph(fg) < 0) { av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit(1); + exit_program(1); } for (j = 0; j < fg->nb_outputs; j++) { OutputStream *ost = fg->outputs[j]->ost; @@ -1653,6 +1664,8 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) f = decoded_frame; err = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, AV_BUFFERSRC_FLAG_PUSH); + if (err == AVERROR_EOF) + err = 0; /* ignore */ if (err < 0) break; } @@ -1666,7 +1679,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) { AVFrame *decoded_frame, *f; - void *buffer_to_free = NULL; int i, ret = 0, err = 0, resample_changed; int64_t best_effort_timestamp; AVRational *frame_sample_aspect; @@ -1682,6 +1694,10 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) ret = avcodec_decode_video2(ist->st->codec, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); + + if (*got_output || ret<0 || pkt->size) + decode_error_stat[ret<0] ++; + if (!*got_output || ret < 0) { if (!pkt->size) { for (i = 0; i < ist->nb_filters; i++) @@ -1697,6 +1713,13 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) if(ist->top_field_first>=0) decoded_frame->top_field_first = ist->top_field_first; + if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) { + err = ist->hwaccel_retrieve_data(ist->st->codec, decoded_frame); + if (err < 0) + goto fail; + } + ist->hwaccel_retrieved_pix_fmt = decoded_frame->format; + best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame); if(best_effort_timestamp != AV_NOPTS_VALUE) ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q); @@ -1712,11 +1735,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } pkt->size = 0; -#if FF_API_DEINTERLACE - pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free); -#endif - - rate_emu_sleep(ist); if (ist->st->sample_aspect_ratio.num) decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; @@ -1739,7 +1757,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) if (ist_in_filtergraph(filtergraphs[i], ist) && ist->reinit_filters && configure_filtergraph(filtergraphs[i]) < 0) { av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit(1); + exit_program(1); } } } @@ -1756,17 +1774,19 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) break; } else f = decoded_frame; - if(av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, - AV_BUFFERSRC_FLAG_PUSH)<0) { - av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n"); - exit(1); + ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, AV_BUFFERSRC_FLAG_PUSH); + if (ret == AVERROR_EOF) { + ret = 0; /* ignore */ + } else if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, + "Failed to inject frame into filter network: %s\n", av_err2str(ret)); + exit_program(1); } - } +fail: av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); - av_free(buffer_to_free); return err < 0 ? err : ret; } @@ -1775,6 +1795,10 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) AVSubtitle subtitle; int i, ret = avcodec_decode_subtitle2(ist->st->codec, &subtitle, got_output, pkt); + + if (*got_output || ret<0 || pkt->size) + decode_error_stat[ret<0] ++; + if (ret < 0 || !*got_output) { if (!pkt->size) sub2video_flush(ist); @@ -1782,27 +1806,32 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) } if (ist->fix_sub_duration) { + int end = 1; if (ist->prev_sub.got_output) { - int end = av_rescale(subtitle.pts - ist->prev_sub.subtitle.pts, - 1000, AV_TIME_BASE); + end = av_rescale(subtitle.pts - ist->prev_sub.subtitle.pts, + 1000, AV_TIME_BASE); if (end < ist->prev_sub.subtitle.end_display_time) { av_log(ist->st->codec, AV_LOG_DEBUG, - "Subtitle duration reduced from %d to %d\n", - ist->prev_sub.subtitle.end_display_time, end); + "Subtitle duration reduced from %d to %d%s\n", + ist->prev_sub.subtitle.end_display_time, end, + end <= 0 ? ", dropping it" : ""); ist->prev_sub.subtitle.end_display_time = end; } } FFSWAP(int, *got_output, ist->prev_sub.got_output); FFSWAP(int, ret, ist->prev_sub.ret); FFSWAP(AVSubtitle, subtitle, ist->prev_sub.subtitle); + if (end <= 0) + goto out; } - sub2video_update(ist, &subtitle); - - if (!*got_output || !subtitle.num_rects) + if (!*got_output) return ret; - rate_emu_sleep(ist); + sub2video_update(ist, &subtitle); + + if (!subtitle.num_rects) + goto out; for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; @@ -1813,6 +1842,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle); } +out: avsubtitle_free(&subtitle); return ret; } @@ -1821,7 +1851,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) static int output_packet(InputStream *ist, const AVPacket *pkt) { int ret = 0, i; - int got_output; + int got_output = 0; AVPacket avpkt; if (!ist->saw_first_ts) { @@ -1920,7 +1950,6 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) /* handle stream copy */ if (!ist->decoding_needed) { - rate_emu_sleep(ist); ist->dts = ist->next_dts; switch (ist->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -1928,7 +1957,12 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) ist->st->codec->sample_rate; break; case AVMEDIA_TYPE_VIDEO: - if (pkt->duration) { + if (ist->framerate.num) { + // TODO: Remove work-around for c99-to-c89 issue 7 + AVRational time_base_q = AV_TIME_BASE_Q; + int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); + ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); + } else if (pkt->duration) { ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); } else if(ist->st->codec->time_base.num != 0) { int ticks= ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->st->codec->ticks_per_frame; @@ -1960,7 +1994,7 @@ static void print_sdp(void) AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files); if (!avc) - exit(1); + exit_program(1); for (i = 0; i < nb_output_files; i++) avc[i] = output_files[i]->ctx; @@ -1970,6 +2004,63 @@ static void print_sdp(void) av_freep(&avc); } +static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt) +{ + int i; + for (i = 0; hwaccels[i].name; i++) + if (hwaccels[i].pix_fmt == pix_fmt) + return &hwaccels[i]; + return NULL; +} + +static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) +{ + InputStream *ist = s->opaque; + const enum AVPixelFormat *p; + int ret; + + for (p = pix_fmts; *p != -1; p++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); + const HWAccel *hwaccel; + + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + break; + + hwaccel = get_hwaccel(*p); + if (!hwaccel || + (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) || + (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id)) + continue; + + ret = hwaccel->init(s); + if (ret < 0) { + if (ist->hwaccel_id == hwaccel->id) { + av_log(NULL, AV_LOG_FATAL, + "%s hwaccel requested for input stream #%d:%d, " + "but cannot be initialized.\n", hwaccel->name, + ist->file_index, ist->st->index); + exit_program(1); + } + continue; + } + ist->active_hwaccel_id = hwaccel->id; + ist->hwaccel_pix_fmt = *p; + break; + } + + return *p; +} + +static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags) +{ + InputStream *ist = s->opaque; + + if (ist->hwaccel_get_buffer && frame->format == ist->hwaccel_pix_fmt) + return ist->hwaccel_get_buffer(s, frame, flags); + + return avcodec_default_get_buffer2(s, frame, flags); +} + static int init_input_stream(int ist_index, char *error, int error_len) { int ret; @@ -1983,15 +2074,26 @@ static int init_input_stream(int ist_index, char *error, int error_len) return AVERROR(EINVAL); } + ist->st->codec->opaque = ist; + ist->st->codec->get_format = get_format; + ist->st->codec->get_buffer2 = get_buffer; + ist->st->codec->thread_safe_callbacks = 1; + av_opt_set_int(ist->st->codec, "refcounted_frames", 1, 0); if (!av_dict_get(ist->opts, "threads", NULL, 0)) av_dict_set(&ist->opts, "threads", "auto", 0); if ((ret = avcodec_open2(ist->st->codec, codec, &ist->opts)) < 0) { + char errbuf[128]; if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 0); - snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d", - ist->file_index, ist->st->index); + + av_strerror(ret, errbuf, sizeof(errbuf)); + + snprintf(error, error_len, + "Error while opening decoder for input stream " + "#%d:%d : %s", + ist->file_index, ist->st->index, errbuf); return ret; } assert_avoptions(ist->opts); @@ -2031,7 +2133,7 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, pts = av_malloc(sizeof(*pts) * size); if (!pts) { av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); - exit(1); + exit_program(1); } p = kf; @@ -2051,7 +2153,7 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, sizeof(*pts)))) { av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); - exit(1); + exit_program(1); } t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0; t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base); @@ -2105,6 +2207,21 @@ static int transcode_init(void) char error[1024]; int want_sdp = 1; + for (i = 0; i < nb_filtergraphs; i++) { + FilterGraph *fg = filtergraphs[i]; + for (j = 0; j < fg->nb_outputs; j++) { + OutputFilter *ofilter = fg->outputs[j]; + if (!ofilter->ost || ofilter->ost->source_index >= 0) + continue; + if (fg->nb_inputs != 1) + continue; + for (k = nb_input_streams-1; k >= 0 ; k--) + if (fg->inputs[0]->ist == input_streams[k]) + break; + ofilter->ost->source_index = k; + } + } + /* init framerate emulation */ for (i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; @@ -2146,9 +2263,19 @@ static int transcode_init(void) ost->st->disposition = ist->st->disposition; codec->bits_per_raw_sample = icodec->bits_per_raw_sample; codec->chroma_sample_location = icodec->chroma_sample_location; + } else { + for (j=0; j<oc->nb_streams; j++) { + AVStream *st = oc->streams[j]; + if (st != ost->st && st->codec->codec_type == codec->codec_type) + break; + } + if (j == oc->nb_streams) + if (codec->codec_type == AVMEDIA_TYPE_AUDIO || codec->codec_type == AVMEDIA_TYPE_VIDEO) + ost->st->disposition = AV_DISPOSITION_DEFAULT; } if (ost->stream_copy) { + AVRational sar; uint64_t extra_size; av_assert0(ist && !ost->filter); @@ -2226,17 +2353,21 @@ static int transcode_init(void) codec->time_base = icodec->time_base; } + if (ist && !ost->frame_rate.num) + ost->frame_rate = ist->framerate; if(ost->frame_rate.num) codec->time_base = av_inv_q(ost->frame_rate); av_reduce(&codec->time_base.num, &codec->time_base.den, codec->time_base.num, codec->time_base.den, INT_MAX); + ost->parser = av_parser_init(codec->codec_id); + switch (codec->codec_type) { case AVMEDIA_TYPE_AUDIO: if (audio_volume != 256) { av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n"); - exit(1); + exit_program(1); } codec->channel_layout = icodec->channel_layout; codec->sample_rate = icodec->sample_rate; @@ -2244,6 +2375,7 @@ static int transcode_init(void) codec->frame_size = icodec->frame_size; codec->audio_service_type = icodec->audio_service_type; codec->block_align = icodec->block_align; + codec->delay = icodec->delay; if((codec->block_align == 1 || codec->block_align == 1152 || codec->block_align == 576) && codec->codec_id == AV_CODEC_ID_MP3) codec->block_align= 0; if(codec->codec_id == AV_CODEC_ID_AC3) @@ -2254,13 +2386,18 @@ static int transcode_init(void) codec->width = icodec->width; codec->height = icodec->height; codec->has_b_frames = icodec->has_b_frames; - if (!codec->sample_aspect_ratio.num) { - codec->sample_aspect_ratio = - ost->st->sample_aspect_ratio = - ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio : - ist->st->codec->sample_aspect_ratio.num ? - ist->st->codec->sample_aspect_ratio : (AVRational){0, 1}; + if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option + sar = + av_mul_q(ost->frame_aspect_ratio, + (AVRational){ codec->height, codec->width }); + av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " + "with stream copy may produce invalid files\n"); } + else if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = icodec->sample_aspect_ratio; + ost->st->sample_aspect_ratio = codec->sample_aspect_ratio = sar; ost->st->avg_frame_rate = ist->st->avg_frame_rate; break; case AVMEDIA_TYPE_SUBTITLE: @@ -2295,7 +2432,7 @@ static int transcode_init(void) fg = init_simple_filtergraph(ist, ost); if (configure_filtergraph(fg)) { av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n"); - exit(1); + exit_program(1); } } @@ -2326,7 +2463,7 @@ static int transcode_init(void) if (ost->filter && !(codec->time_base.num && codec->time_base.den)) codec->time_base = ost->filter->filter->inputs[0]->time_base; if ( av_q2d(codec->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH - && (video_sync_method == VSYNC_CFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){ + && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){ av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); } @@ -2338,16 +2475,23 @@ static int transcode_init(void) codec->width = ost->filter->filter->inputs[0]->w; codec->height = ost->filter->filter->inputs[0]->h; codec->sample_aspect_ratio = ost->st->sample_aspect_ratio = - ost->frame_aspect_ratio ? // overridden by the -aspect cli option - av_d2q(ost->frame_aspect_ratio * codec->height/codec->width, 255) : + ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option + av_mul_q(ost->frame_aspect_ratio, (AVRational){ codec->height, codec->width }) : ost->filter->filter->inputs[0]->sample_aspect_ratio; if (!strncmp(ost->enc->name, "libx264", 7) && codec->pix_fmt == AV_PIX_FMT_NONE && ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P) - av_log(NULL, AV_LOG_INFO, + av_log(NULL, AV_LOG_WARNING, "No pixel format specified, %s for H.264 encoding chosen.\n" "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); + if (!strncmp(ost->enc->name, "mpeg2video", 10) && + codec->pix_fmt == AV_PIX_FMT_NONE && + ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P) + av_log(NULL, AV_LOG_WARNING, + "No pixel format specified, %s for MPEG-2 encoding chosen.\n" + "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", + av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); codec->pix_fmt = ost->filter->filter->inputs[0]->format; if (!icodec || @@ -2404,16 +2548,16 @@ static int transcode_init(void) if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) { av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", logfilename); - exit(1); + exit_program(1); } codec->stats_in = logbuffer; } if (codec->flags & CODEC_FLAG_PASS1) { - f = fopen(logfilename, "wb"); + f = av_fopen_utf8(logfilename, "wb"); if (!f) { av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno)); - exit(1); + exit_program(1); } ost->logfile = f; } @@ -2459,9 +2603,6 @@ static int transcode_init(void) av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." " It takes bits/s as argument, not kbits/s\n"); extra_size += ost->st->codec->extradata_size; - - if (ost->st->codec->me_threshold) - input_streams[ost->source_index]->st->codec->debug |= FF_DEBUG_MV; } else { av_opt_set_dict(ost->st->codec, &ost->opts); } @@ -2499,10 +2640,11 @@ static int transcode_init(void) oc->interrupt_callback = int_cb; if ((ret = avformat_write_header(oc, &output_files[i]->opts)) < 0) { char errbuf[128]; - const char *errbuf_ptr = errbuf; - if (av_strerror(ret, errbuf, sizeof(errbuf)) < 0) - errbuf_ptr = strerror(AVUNERROR(ret)); - snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?): %s", i, errbuf_ptr); + av_strerror(ret, errbuf, sizeof(errbuf)); + snprintf(error, sizeof(error), + "Could not write header for output file #%d " + "(incorrect codec parameters ?): %s", + i, errbuf); ret = AVERROR(EINVAL); goto dump_format; } @@ -2666,7 +2808,7 @@ static int check_keyboard_interaction(int64_t cur_time) char buf[4096], target[64], command[256], arg[256] = {0}; double time; int k, n = 0; - fprintf(stderr, "\nEnter command: <target> <time> <command>[ <argument>]\n"); + fprintf(stderr, "\nEnter command: <target>|all <time>|-1 <command>[ <argument>]\n"); i = 0; while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1) if (k > 0) @@ -2682,7 +2824,10 @@ static int check_keyboard_interaction(int64_t cur_time) if (time < 0) { ret = avfilter_graph_send_command(fg->graph, target, command, arg, buf, sizeof(buf), key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0); - fprintf(stderr, "Command reply for stream %d: ret:%d res:%s\n", i, ret, buf); + fprintf(stderr, "Command reply for stream %d: ret:%d res:\n%s", i, ret, buf); + } else if (key == 'c') { + fprintf(stderr, "Queing commands only on filters supporting the specific command is unsupported\n"); + ret = AVERROR_PATCHWELCOME; } else { ret = avfilter_graph_queue_command(fg->graph, target, command, arg, 0, time); } @@ -2719,7 +2864,8 @@ static int check_keyboard_interaction(int64_t cur_time) "? show this help\n" "+ increase verbosity\n" "- decrease verbosity\n" - "c Send command to filtergraph\n" + "c Send command to first matching filter supporting it\n" + "C Send/Que command to all matching filters\n" "D cycle through available debug modes\n" "h dump packets/hex press to cycle through the 3 states\n" "q quit\n" @@ -2841,6 +2987,17 @@ static int get_input_packet_mt(InputFile *f, AVPacket *pkt) static int get_input_packet(InputFile *f, AVPacket *pkt) { + if (f->rate_emu) { + int i; + for (i = 0; i < f->nb_streams; i++) { + InputStream *ist = input_streams[f->ist_index + i]; + int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); + int64_t now = av_gettime() - ist->start; + if (pts > now) + return AVERROR(EAGAIN); + } + } + #if HAVE_PTHREADS if (nb_input_files > 1) return get_input_packet_mt(f, pkt); @@ -2892,7 +3049,7 @@ static int process_input(int file_index) if (ret != AVERROR_EOF) { print_error(is->filename, ret); if (exit_on_error) - exit(1); + exit_program(1); } ifile->eof_reached = 1; @@ -2988,6 +3145,23 @@ static int process_input(int file_index) if (pkt.dts != AV_NOPTS_VALUE) pkt.dts *= ist->ts_scale; + if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts == AV_NOPTS_VALUE && !copy_ts + && (is->iformat->flags & AVFMT_TS_DISCONT) && ifile->last_ts != AV_NOPTS_VALUE) { + int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); + int64_t delta = pkt_dts - ifile->last_ts; + if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || + (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && + ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)){ + ifile->ts_offset -= delta; + av_log(NULL, AV_LOG_DEBUG, + "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", + delta, ifile->ts_offset); + pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + } + } + if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) { int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); @@ -2996,7 +3170,7 @@ static int process_input(int file_index) if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || - pkt_dts+1<ist->pts){ + pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)){ ifile->ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", @@ -3025,6 +3199,9 @@ static int process_input(int file_index) } } + if (pkt.dts != AV_NOPTS_VALUE) + ifile->last_ts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); + if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->st->codec->codec_type), @@ -3043,7 +3220,7 @@ static int process_input(int file_index) av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", ist->file_index, ist->st->index, buf); if (exit_on_error) - exit(1); + exit_program(1); } discard_packet: @@ -3234,6 +3411,8 @@ static int transcode(void) ist = input_streams[i]; if (ist->decoding_needed) { avcodec_close(ist->st->codec); + if (ist->hwaccel_uninit) + ist->hwaccel_uninit(ist->st->codec); } } @@ -3256,7 +3435,8 @@ static int transcode(void) ost->logfile = NULL; } av_freep(&ost->st->codec->subtitle_header); - av_free(ost->forced_kf_pts); + av_freep(&ost->forced_kf_pts); + av_freep(&ost->apad); av_dict_free(&ost->opts); av_dict_free(&ost->swr_opts); av_dict_free(&ost->resample_opts); @@ -3312,7 +3492,7 @@ int main(int argc, char **argv) int ret; int64_t ti; - atexit(exit_program); + register_exit(ffmpeg_cleanup); setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */ @@ -3341,33 +3521,37 @@ int main(int argc, char **argv) /* parse options and open all input/output files */ ret = ffmpeg_parse_options(argc, argv); if (ret < 0) - exit(1); + exit_program(1); if (nb_output_files <= 0 && nb_input_files == 0) { show_usage(); av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name); - exit(1); + exit_program(1); } /* file converter / grab */ if (nb_output_files <= 0) { av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n"); - exit(1); + exit_program(1); } // if (nb_input_files == 0) { // av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n"); -// exit(1); +// exit_program(1); // } current_time = ti = getutime(); if (transcode() < 0) - exit(1); + exit_program(1); ti = getutime() - ti; if (do_benchmark) { printf("bench: utime=%0.3fs\n", ti / 1000000.0); } + av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n", + decode_error_stat[0], decode_error_stat[1]); + if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1]) + exit_program(69); - exit(received_nb_signals ? 255 : 0); + exit_program(received_nb_signals ? 255 : 0); return 0; } |
