X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=5be745e42f54bac31377dfe8023fa5815222035f;hb=b27e2b6e12461b0f60204c7f0145609a6db1697b;hp=2763db6deebdb0a6afa2c0eceff73783a504cebf;hpb=40112e7b3589e1cf37cd80a7d2e8baad4cb8c523;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index 2763db6deeb..5be745e42f5 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -31,8 +31,13 @@ #include #include #if HAVE_ISATTY +#if HAVE_IO_H +#include +#endif +#if HAVE_UNISTD_H #include #endif +#endif #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" @@ -197,13 +202,14 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts) AV_BUFFERSRC_FLAG_PUSH); } -static void sub2video_update(InputStream *ist, AVSubtitle *sub, int64_t pts) +static void sub2video_update(InputStream *ist, AVSubtitle *sub) { int w = ist->sub2video.w, h = ist->sub2video.h; AVFilterBufferRef *ref = ist->sub2video.ref; int8_t *dst; int dst_linesize; int i; + int64_t pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ist->st->time_base); if (!ref) return; @@ -372,7 +378,7 @@ static int decode_interrupt_cb(void *ctx) const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; -void av_noreturn exit_program(int ret) +static void exit_program(void) { int i, j; @@ -411,11 +417,11 @@ void av_noreturn exit_program(int ret) bsfc = next; } output_streams[i]->bitstream_filters = NULL; + avcodec_free_frame(&output_streams[i]->filtered_frame); av_freep(&output_streams[i]->forced_keyframes); av_freep(&output_streams[i]->avfilter); av_freep(&output_streams[i]->logfile_prefix); - av_freep(&output_streams[i]->filtered_frame); av_freep(&output_streams[i]); } for (i = 0; i < nb_input_files; i++) { @@ -423,7 +429,7 @@ void av_noreturn exit_program(int ret) av_freep(&input_files[i]); } for (i = 0; i < nb_input_streams; i++) { - av_freep(&input_streams[i]->decoded_frame); + avcodec_free_frame(&input_streams[i]->decoded_frame); av_dict_free(&input_streams[i]->opts); free_buffer_pool(&input_streams[i]->buffer_pool); avfilter_unref_bufferp(&input_streams[i]->sub2video.ref); @@ -450,8 +456,6 @@ void av_noreturn exit_program(int ret) (int) received_sigterm); exit (255); } - - exit(ret); } void assert_avoptions(AVDictionary *m) @@ -459,7 +463,7 @@ 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_program(1); + exit(1); } } @@ -476,7 +480,7 @@ static void assert_codec_experimental(AVCodecContext *c, int encoder) if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL)) av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n", codec_string, codec->name); - exit_program(1); + exit(1); } } @@ -558,7 +562,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) avctx->codec ? avctx->codec->name : "copy"); print_error("", a); if (exit_on_error) - exit_program(1); + exit(1); } *pkt = new_pkt; @@ -566,10 +570,21 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) } pkt->stream_index = ost->index; + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "muxer <- type:%s " + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s size:%d\n", + av_get_media_type_string(ost->st->codec->codec_type), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), + pkt->size + ); + } + ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { print_error("av_interleaved_write_frame()", ret); - exit_program(1); + exit(1); } } @@ -620,7 +635,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_program(1); + exit(1); } update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); @@ -639,9 +654,9 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); } + audio_size += pkt.size; write_frame(s, &pkt, ost); - audio_size += pkt.size; av_free_packet(&pkt); } } @@ -688,18 +703,18 @@ static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void * static void do_subtitle_out(AVFormatContext *s, OutputStream *ost, InputStream *ist, - AVSubtitle *sub, - int64_t pts) + AVSubtitle *sub) { int subtitle_out_max_size = 1024 * 1024; int subtitle_out_size, nb, i; AVCodecContext *enc; AVPacket pkt; + int64_t pts; - if (pts == AV_NOPTS_VALUE) { + if (sub->pts == AV_NOPTS_VALUE) { av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); if (exit_on_error) - exit_program(1); + exit(1); return; } @@ -718,8 +733,7 @@ static void do_subtitle_out(AVFormatContext *s, nb = 1; /* shift timestamp to honor -ss and make check_recording_time() work with -t */ - pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q) - - output_files[ost->file_index]->start_time; + pts = sub->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)) @@ -736,7 +750,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_program(1); + exit(1); } av_init_packet(&pkt); @@ -752,8 +766,8 @@ static void do_subtitle_out(AVFormatContext *s, else pkt.pts += 90 * sub->end_display_time; } - write_frame(s, &pkt, ost); subtitle_size += pkt.size; + write_frame(s, &pkt, ost); } } @@ -816,7 +830,7 @@ static void do_video_out(AVFormatContext *s, return; } else if (nb_frames > 1) { if (nb_frames > dts_error_threshold * 30) { - av_log(NULL, AV_LOG_ERROR, "%d frame duplication too large, skiping\n", nb_frames - 1); + av_log(NULL, AV_LOG_ERROR, "%d frame duplication too large, skipping\n", nb_frames - 1); nb_frames_drop++; return; } @@ -847,8 +861,8 @@ static void do_video_out(AVFormatContext *s, pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; - write_frame(s, &pkt, ost); video_size += pkt.size; + write_frame(s, &pkt, ost); } else { int got_packet; AVFrame big_picture; @@ -879,7 +893,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_program(1); + exit(1); } if (got_packet) { @@ -898,9 +912,9 @@ static void do_video_out(AVFormatContext *s, av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); } - write_frame(s, &pkt, ost); frame_size = pkt.size; video_size += pkt.size; + write_frame(s, &pkt, ost); av_free_packet(&pkt); /* if two pass, output log */ @@ -939,7 +953,7 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost, vstats_file = fopen(vstats_filename, "w"); if (!vstats_file) { perror("fopen"); - exit_program(1); + exit(1); } } @@ -1272,7 +1286,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_program(1); + exit(1); } *size += pkt.size; if (ost->logfile && enc->stats_out) { @@ -1325,6 +1339,10 @@ 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 (of->recording_time != INT64_MAX && ist->pts >= of->recording_time + of->start_time) { close_output_stream(ost); @@ -1461,7 +1479,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_program(1); + exit(1); } decoded_frame->channel_layout = avctx->channel_layout; @@ -1489,7 +1507,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_program(1); + exit(1); } for (j = 0; j < fg->nb_outputs; j++) { OutputStream *ost = fg->outputs[j]->ost; @@ -1604,7 +1622,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) if (ist_in_filtergraph(filtergraphs[i], ist) && configure_filtergraph(filtergraphs[i]) < 0) { av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit_program(1); + exit(1); } } @@ -1640,7 +1658,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } else if(av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, AV_BUFFERSRC_FLAG_PUSH)<0) { av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n"); - exit_program(1); + exit(1); } } @@ -1652,7 +1670,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) { AVSubtitle subtitle; - int64_t pts = pkt->pts; int i, ret = avcodec_decode_subtitle2(ist->st->codec, &subtitle, got_output, pkt); if (ret < 0 || !*got_output) { @@ -1663,8 +1680,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) if (ist->fix_sub_duration) { if (ist->prev_sub.got_output) { - int end = av_rescale_q(pts - ist->prev_sub.pts, ist->st->time_base, - (AVRational){ 1, 1000 }); + int 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", @@ -1672,26 +1689,25 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) ist->prev_sub.subtitle.end_display_time = end; } } - FFSWAP(int64_t, pts, ist->prev_sub.pts); FFSWAP(int, *got_output, ist->prev_sub.got_output); FFSWAP(int, ret, ist->prev_sub.ret); FFSWAP(AVSubtitle, subtitle, ist->prev_sub.subtitle); } + sub2video_update(ist, &subtitle); + if (!*got_output || !subtitle.num_rects) return ret; rate_emu_sleep(ist); - sub2video_update(ist, &subtitle, pkt->pts); - for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; if (!check_output_constraints(ist, ost) || !ost->encoding_needed) continue; - do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle, pts); + do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle); } avsubtitle_free(&subtitle); @@ -1841,7 +1857,7 @@ static void print_sdp(void) AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files); if (!avc) - exit_program(1); + exit(1); for (i = 0; i < nb_output_files; i++) avc[i] = output_files[i]->ctx; @@ -1909,7 +1925,7 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n); if (!ost->forced_kf_pts) { av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); - exit_program(1); + exit(1); } p = kf; @@ -2054,8 +2070,10 @@ static int transcode_init(void) } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS) && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp") && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod") + && strcmp(oc->oformat->name, "f4v") ) { - if( copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) + if( copy_tb<0 && icodec->time_base.den + && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/500 || copy_tb==0){ codec->time_base = icodec->time_base; @@ -2073,7 +2091,7 @@ static int transcode_init(void) 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_program(1); + exit(1); } codec->channel_layout = icodec->channel_layout; codec->sample_rate = icodec->sample_rate; @@ -2220,7 +2238,7 @@ 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_program(1); + exit(1); } codec->stats_in = logbuffer; } @@ -2229,7 +2247,7 @@ static int transcode_init(void) if (!f) { av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno)); - exit_program(1); + exit(1); } ost->logfile = f; } @@ -2704,7 +2722,7 @@ static int process_input(int file_index) if (ret != AVERROR_EOF) { print_error(is->filename, ret); if (exit_on_error) - exit_program(1); + exit(1); } ifile->eof_reached = 1; @@ -2825,7 +2843,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_program(1); + exit(1); } discard_packet: @@ -3099,8 +3117,12 @@ int main(int argc, char **argv) OptionsContext o = { 0 }; int64_t ti; + atexit(exit_program); + reset_options(&o, 0); + setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */ + av_log_set_flags(AV_LOG_SKIP_REPEATED); parse_loglevel(argc, argv, options); @@ -3131,29 +3153,29 @@ int main(int argc, char **argv) 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_program(1); + exit(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_program(1); + exit(1); } // if (nb_input_files == 0) { // av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n"); -// exit_program(1); +// exit(1); // } current_time = ti = getutime(); if (transcode() < 0) - exit_program(1); + exit(1); ti = getutime() - ti; if (do_benchmark) { int maxrss = getmaxrss() / 1024; printf("bench: utime=%0.3fs maxrss=%ikB\n", ti / 1000000.0, maxrss); } - exit_program(0); + exit(0); return 0; }