日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ffmpeg 之ffmpeg 整理流程分析

發布時間:2023/12/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ffmpeg 之ffmpeg 整理流程分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這個篇文檔主要對ffmpeg? 命令分析:主要分析ffmpeg 程序主要流程:

?1. 分析命令行函數,解析出輸入文件及輸出文件

?ffmpeg_parse_option?

int ffmpeg_parse_options(int argc, char **argv) {OptionParseContext octx;uint8_t error[128];int ret;memset(&octx, 0, sizeof(octx));/* split the commandline into an internal representation */ret = split_commandline(&octx, argc, argv, options, groups,FF_ARRAY_ELEMS(groups));if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error splitting the argument list: ");goto fail;}/* apply global options */ret = parse_optgroup(NULL, &octx.global_opts);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error parsing global options: ");goto fail;}/* configure terminal and setup signal handlers */term_init();/* open input files */ret = open_files(&octx.groups[GROUP_INFILE], "input", open_input_file);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error opening input files: ");goto fail;}/* create the complex filtergraphs */ret = init_complex_filters();if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error initializing complex filters.\n");goto fail;}/* open output files */ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error opening output files: ");goto fail;}check_filter_outputs();fail:uninit_parse_context(&octx);if (ret < 0) {av_strerror(ret, error, sizeof(error));av_log(NULL, AV_LOG_FATAL, "%s\n", error);}return ret; }

2.?transcode 轉碼處理

static int transcode(void) {int ret, i;AVFormatContext *os;OutputStream *ost;InputStream *ist;int64_t timer_start;int64_t total_packets_written = 0;ret = transcode_init(); // 轉碼初始化if (ret < 0)goto fail;if (stdin_interaction) {av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");}timer_start = av_gettime_relative();#if HAVE_THREADSif ((ret = init_input_threads()) < 0)goto fail; #endifwhile (!received_sigterm) {int64_t cur_time= av_gettime_relative();/* if 'q' pressed, exits */if (stdin_interaction)if (check_keyboard_interaction(cur_time) < 0)break;/* check if there's any stream where output is still needed */if (!need_output()) {av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n");break;}ret = transcode_step();if (ret < 0 && ret != AVERROR_EOF) {av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));break;}/* dump report by using the output first video and audio streams */print_report(0, timer_start, cur_time);} #if HAVE_THREADSfree_input_threads(); #endif/* at the end of stream, we must flush the decoder buffers */for (i = 0; i < nb_input_streams; i++) {ist = input_streams[i];if (!input_files[ist->file_index]->eof_reached) {process_input_packet(ist, NULL, 0);}}flush_encoders();term_exit();/* write the trailer if needed and close file */for (i = 0; i < nb_output_files; i++) {os = output_files[i]->ctx;if (!output_files[i]->header_written) {av_log(NULL, AV_LOG_ERROR,"Nothing was written into output file %d (%s), because ""at least one of its streams received no packets.\n",i, os->url);continue;}if ((ret = av_write_trailer(os)) < 0) {av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", os->url, av_err2str(ret));if (exit_on_error)exit_program(1);}}/* dump report by using the first video and audio streams */print_report(1, timer_start, av_gettime_relative());/* close each encoder */for (i = 0; i < nb_output_streams; i++) {ost = output_streams[i];if (ost->encoding_needed) {av_freep(&ost->enc_ctx->stats_in);}total_packets_written += ost->packets_written;if (!ost->packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) {av_log(NULL, AV_LOG_FATAL, "Empty output on stream %d.\n", i);exit_program(1);}}if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) {av_log(NULL, AV_LOG_FATAL, "Empty output\n");exit_program(1);}/* close each decoder */for (i = 0; i < nb_input_streams; i++) {ist = input_streams[i];if (ist->decoding_needed) {avcodec_close(ist->dec_ctx);if (ist->hwaccel_uninit)ist->hwaccel_uninit(ist->dec_ctx);}}hw_device_free_all();/* finished ! */ret = 0;fail: #if HAVE_THREADSfree_input_threads(); #endifif (output_streams) {for (i = 0; i < nb_output_streams; i++) {ost = output_streams[i];if (ost) {if (ost->logfile) {if (fclose(ost->logfile))av_log(NULL, AV_LOG_ERROR,"Error closing logfile, loss of information possible: %s\n",av_err2str(AVERROR(errno)));ost->logfile = NULL;}av_freep(&ost->forced_kf_pts);av_freep(&ost->apad);av_freep(&ost->disposition);av_dict_free(&ost->encoder_opts);av_dict_free(&ost->sws_dict);av_dict_free(&ost->swr_opts);av_dict_free(&ost->resample_opts);}}}return ret; }

? 2.1? transcode_step? ? ?// 轉換流程。
? ? ? ? ? ? ? ?process_input
? ? ? ? ? ? ? ? ? ? ? process_input_packet

/* pkt = NULL means EOF (needed to flush decoder buffers) */ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) {int ret = 0, i;int repeating = 0;int eof_reached = 0;AVPacket avpkt;if (!ist->saw_first_ts) {ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;ist->pts = 0;if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) {ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong}ist->saw_first_ts = 1;}if (ist->next_dts == AV_NOPTS_VALUE)ist->next_dts = ist->dts;if (ist->next_pts == AV_NOPTS_VALUE)ist->next_pts = ist->pts;if (!pkt) {/* EOF handling */av_init_packet(&avpkt);avpkt.data = NULL;avpkt.size = 0;} else {avpkt = *pkt;}if (pkt && pkt->dts != AV_NOPTS_VALUE) {ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)ist->next_pts = ist->pts = ist->dts;}// while we have more to decode or while the decoder did output something on EOFwhile (ist->decoding_needed) {int64_t duration_dts = 0;int64_t duration_pts = 0;int got_output = 0;int decode_failed = 0;ist->pts = ist->next_pts;ist->dts = ist->next_dts;switch (ist->dec_ctx->codec_type) {case AVMEDIA_TYPE_AUDIO:ret = decode_audio (ist, repeating ? NULL : &avpkt, &got_output,&decode_failed);break;case AVMEDIA_TYPE_VIDEO:ret = decode_video (ist, repeating ? NULL : &avpkt, &got_output, &duration_pts, !pkt,&decode_failed);if (!repeating || !pkt || got_output) {if (pkt && pkt->duration) {duration_dts = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);} else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) {int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->dec_ctx->ticks_per_frame;duration_dts = ((int64_t)AV_TIME_BASE *ist->dec_ctx->framerate.den * ticks) /ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame;}if(ist->dts != AV_NOPTS_VALUE && duration_dts) {ist->next_dts += duration_dts;}elseist->next_dts = AV_NOPTS_VALUE;}if (got_output) {if (duration_pts > 0) {ist->next_pts += av_rescale_q(duration_pts, ist->st->time_base, AV_TIME_BASE_Q);} else {ist->next_pts += duration_dts;}}break;case AVMEDIA_TYPE_SUBTITLE:if (repeating)break;ret = transcode_subtitles(ist, &avpkt, &got_output, &decode_failed);if (!pkt && ret >= 0)ret = AVERROR_EOF;break;default:return -1;}if (ret == AVERROR_EOF) {eof_reached = 1;break;}if (ret < 0) {if (decode_failed) {av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n",ist->file_index, ist->st->index, av_err2str(ret));} else {av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded ""data for stream #%d:%d\n", ist->file_index, ist->st->index);}if (!decode_failed || exit_on_error)exit_program(1);break;}if (got_output)ist->got_output = 1;if (!got_output)break;// During draining, we might get multiple output frames in this loop.// ffmpeg.c does not drain the filter chain on configuration changes,// which means if we send multiple frames at once to the filters, and// one of those frames changes configuration, the buffered frames will// be lost. This can upset certain FATE tests.// Decode only 1 frame per call on EOF to appease these FATE tests.// The ideal solution would be to rewrite decoding to use the new// decoding API in a better way.if (!pkt)break;repeating = 1;}/* after flushing, send an EOF on all the filter inputs attached to the stream *//* except when looping we need to flush but not to send an EOF */if (!pkt && ist->decoding_needed && eof_reached && !no_eof) {int ret = send_filter_eof(ist);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");exit_program(1);}}/* handle stream copy */if (!ist->decoding_needed && pkt) {ist->dts = ist->next_dts;switch (ist->dec_ctx->codec_type) {case AVMEDIA_TYPE_AUDIO:av_assert1(pkt->duration >= 0);if (ist->dec_ctx->sample_rate) {ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /ist->dec_ctx->sample_rate;} else {ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);}break;case AVMEDIA_TYPE_VIDEO:if (ist->framerate.num) {// TODO: Remove work-around for c99-to-c89 issue 7AVRational 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->dec_ctx->framerate.num != 0) {int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame;ist->next_dts += ((int64_t)AV_TIME_BASE *ist->dec_ctx->framerate.den * ticks) /ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame;}break;}ist->pts = ist->dts;ist->next_pts = ist->next_dts;}for (i = 0; i < nb_output_streams; i++) {OutputStream *ost = output_streams[i];if (!check_output_constraints(ist, ost) || ost->encoding_needed)continue;do_streamcopy(ist, ost, pkt); // packet 拷貝到輸出文件}return !eof_reached; }

?3.?do_streamcopy

do_streamcopy
?? ?output_packet
?? ??? ?write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
?? ??? ??? ?av_interleaved_write_frame
?? ??? ??? ??? ?write_packets_common
?? ??? ??? ??? ??? ?write_packet(AVFormatContext *s, AVPacket *pkt)
?? ??? ??? ??? ??? ??? ?s->oformat->write_packet
?? ??? ??? ??? ??? ??? ??? ? AVOutputFormat *oformat; mux ?中函數:? ? ? ? ? ? ? ??

總結

以上是生活随笔為你收集整理的ffmpeg 之ffmpeg 整理流程分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。