X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=7b6123a6b83c15c4af206e4a8227b355f125bee4;hb=de54a96aa8f5959ebd87516d514c77055b369fed;hp=af93880ed805baab027c03a02f184ad4c95c48ff;hpb=a984efd104cc3f4ab7f7209fa1b1bab6a44720db;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index af93880ed80..7b6123a6b83 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -120,6 +120,7 @@ const char *const forced_keyframes_const_names[] = { static void do_video_stats(OutputStream *ost, int frame_size); static int64_t getutime(void); +static int64_t getmaxrss(void); static int run_as_daemon = 0; static int64_t video_size = 0; @@ -167,7 +168,20 @@ static int restore_tty; This is a temporary solution until libavfilter gets real subtitles support. */ +static int sub2video_get_blank_frame(InputStream *ist) +{ + int ret; + AVFrame *frame = ist->sub2video.frame; + av_frame_unref(frame); + ist->sub2video.frame->width = ist->sub2video.w; + ist->sub2video.frame->height = ist->sub2video.h; + ist->sub2video.frame->format = AV_PIX_FMT_RGB32; + if ((ret = av_frame_get_buffer(frame, 32)) < 0) + return ret; + memset(frame->data[0], 0, frame->height * frame->linesize[0]); + return 0; +} static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, AVSubtitleRect *r) @@ -200,28 +214,27 @@ static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, static void sub2video_push_ref(InputStream *ist, int64_t pts) { - AVFilterBufferRef *ref = ist->sub2video.ref; + AVFrame *frame = ist->sub2video.frame; int i; - ist->sub2video.last_pts = ref->pts = pts; + av_assert1(frame->data[0]); + ist->sub2video.last_pts = frame->pts = pts; for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_ref(ist->filters[i]->filter, - avfilter_ref_buffer(ref, ~0), - AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT | - AV_BUFFERSRC_FLAG_NO_COPY | - AV_BUFFERSRC_FLAG_PUSH); + av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame, + AV_BUFFERSRC_FLAG_KEEP_REF | + AV_BUFFERSRC_FLAG_PUSH); } static void sub2video_update(InputStream *ist, AVSubtitle *sub) { int w = ist->sub2video.w, h = ist->sub2video.h; - AVFilterBufferRef *ref = ist->sub2video.ref; + AVFrame *frame = ist->sub2video.frame; int8_t *dst; int dst_linesize; int num_rects, i; int64_t pts, end_pts; - if (!ref) + if (!frame) return; if (sub) { pts = av_rescale_q(sub->pts + sub->start_display_time * 1000, @@ -234,9 +247,13 @@ static void sub2video_update(InputStream *ist, AVSubtitle *sub) end_pts = INT64_MAX; num_rects = 0; } - dst = ref->data [0]; - dst_linesize = ref->linesize[0]; - memset(dst, 0, h * dst_linesize); + if (sub2video_get_blank_frame(ist) < 0) { + av_log(ist->st->codec, AV_LOG_ERROR, + "Impossible to get a blank canvas.\n"); + return; + } + dst = frame->data [0]; + dst_linesize = frame->linesize[0]; for (i = 0; i < num_rects; i++) sub2video_copy_rect(dst, dst_linesize, w, h, sub->rects[i]); sub2video_push_ref(ist, pts); @@ -255,7 +272,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) (possibly overlay) is desperately waiting for a subtitle frame. */ for (i = 0; i < infile->nb_streams; i++) { InputStream *ist2 = input_streams[infile->ist_index + i]; - if (!ist2->sub2video.ref) + if (!ist2->sub2video.frame) continue; /* subtitles seem to be usually muxed ahead of other streams; if not, substracting a larger time here is necessary */ @@ -263,7 +280,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) continue; - if (pts2 >= ist2->sub2video.end_pts) + if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0]) sub2video_update(ist2, NULL); for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++) nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter); @@ -408,6 +425,11 @@ static void exit_program(void) { int i, j; + if (do_benchmark) { + int maxrss = getmaxrss() / 1024; + printf("bench: maxrss=%ikB\n", maxrss); + } + for (i = 0; i < nb_filtergraphs; i++) { avfilter_graph_free(&filtergraphs[i]->graph); for (j = 0; j < filtergraphs[i]->nb_inputs; j++) { @@ -459,7 +481,8 @@ static void exit_program(void) 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); + avsubtitle_free(&input_streams[i]->prev_sub.subtitle); + avcodec_free_frame(&input_streams[i]->sub2video.frame); av_freep(&input_streams[i]->filters); av_freep(&input_streams[i]); } @@ -563,6 +586,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) memcpy(t, new_pkt.data, new_pkt.size); memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE); new_pkt.data = t; + new_pkt.buf = NULL; a = 1; } else a = AVERROR(ENOMEM); @@ -674,6 +698,7 @@ 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; @@ -684,7 +709,7 @@ static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void * dec = ist->st->codec; /* deinterlace : must be done before any resize */ - if (do_deinterlace) { + if (FF_API_DEINTERLACE && do_deinterlace) { int size; /* create temporary picture */ @@ -714,6 +739,7 @@ static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void * *picture = *picture2; *bufp = buf; } +#endif static void do_subtitle_out(AVFormatContext *s, OutputStream *ost, @@ -1214,7 +1240,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti p = psnr(error / scale); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], p); av_bprintf(&buf_script, "stream_%d_%d_psnr_%c=%2.2f\n", - ost->file_index, ost->index, type[i] | 32, p); + ost->file_index, ost->index, type[j] | 32, p); } p = psnr(error_sum / scale_sum); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum)); @@ -1262,7 +1288,10 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti av_bprintf(&buf_script, "drop_frames=%d\n", nb_frames_drop); if (print_stats || is_last_report) { - av_log(NULL, AV_LOG_INFO, "%s \r", buf); + if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) { + fprintf(stderr, "%s \r", buf); + } else + av_log(NULL, AV_LOG_INFO, "%s \r", buf); fflush(stderr); } @@ -1614,8 +1643,9 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) (AVRational){1, ist->st->codec->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, (AVRational){1, ist->st->codec->sample_rate}); for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, - AV_BUFFERSRC_FLAG_PUSH); + av_buffersrc_add_frame_flags(ist->filters[i]->filter, decoded_frame, + AV_BUFFERSRC_FLAG_KEEP_REF | + AV_BUFFERSRC_FLAG_PUSH); decoded_frame->pts = AV_NOPTS_VALUE; @@ -1665,7 +1695,9 @@ 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); @@ -1722,7 +1754,9 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) AV_BUFFERSRC_FLAG_NO_COPY | AV_BUFFERSRC_FLAG_PUSH); } else - if(av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, AV_BUFFERSRC_FLAG_PUSH)<0) { + if(av_buffersrc_add_frame_flags(ist->filters[i]->filter, decoded_frame, + AV_BUFFERSRC_FLAG_KEEP_REF | + AV_BUFFERSRC_FLAG_PUSH)<0) { av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n"); exit(1); } @@ -1946,7 +1980,7 @@ static int init_input_stream(int ist_index, char *error, int error_len) return AVERROR(EINVAL); } - ist->dr1 = (codec->capabilities & CODEC_CAP_DR1) && !do_deinterlace; + ist->dr1 = (codec->capabilities & CODEC_CAP_DR1) && !(FF_API_DEINTERLACE && do_deinterlace); if (codec->type == AVMEDIA_TYPE_VIDEO && ist->dr1) { ist->st->codec->get_buffer = codec_get_buffer; ist->st->codec->release_buffer = codec_release_buffer; @@ -2423,13 +2457,20 @@ static int transcode_init(void) 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); } } /* init input streams */ for (i = 0; i < nb_input_streams; i++) - if ((ret = init_input_stream(i, error, sizeof(error))) < 0) + if ((ret = init_input_stream(i, error, sizeof(error))) < 0) { + for (i = 0; i < nb_output_streams; i++) { + ost = output_streams[i]; + avcodec_close(ost->st->codec); + } goto dump_format; + } /* discard unused programs */ for (i = 0; i < nb_input_files; i++) { @@ -3319,8 +3360,7 @@ int main(int argc, char **argv) exit(1); ti = getutime() - ti; if (do_benchmark) { - int maxrss = getmaxrss() / 1024; - printf("bench: utime=%0.3fs maxrss=%ikB\n", ti / 1000000.0, maxrss); + printf("bench: utime=%0.3fs\n", ti / 1000000.0); } exit(received_nb_signals ? 255 : 0);