transcode_init()函数是在转换前做准备工作的.此处看一下它的真面目,不废话,看注释吧:
//为转换过程做准备 static int transcode_init(OutputFile *output_files, int nb_output_files, InputFile *input_files, int nb_input_files) { int ret = 0, i, j, k; AVFormatContext *oc; AVCodecContext *codec, *icodec; OutputStream *ost; InputStream *ist; char error[1024]; int want_sdp = 1; /* init framerate emulation */ //初始化帧率仿真(转换时是不按帧率来的,但如果要求帧率仿真,就可以做到) for (i = 0; i < nb_input_files; i++) { InputFile *ifile = &input_files[i]; //如果一个输入文件被要求帧率仿真(指的是即使是转换也像播放那样按照帧率来进行), //则为这个文件中所有流记录下开始时间 if (ifile->rate_emu) for (j = 0; j < ifile->nb_streams; j++) input_streams[j + ifile->ist_index].start = av_gettime(); } /* output stream init */ for (i = 0; i < nb_output_files; i++) { //什么也没做,只是做了个判断而已 oc = output_files[i].ctx; if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { av_dump_format(oc, i, oc->filename, 1); av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i); return AVERROR(EINVAL); } } //轮循所有的输出流,跟据对应的输入流,设置其编解码器的参数 for (i = 0; i < nb_output_streams; i++) { //轮循所有的输出流 ost = &output_streams[i]; //输出流对应的FormatContext oc = output_files[ost->file_index].ctx; //取得输出流对应的输入流 ist = &input_streams[ost->source_index]; //attachment_filename是不是这样的东西:一个文件,它单独容纳一个输出流?此处不懂 if (ost->attachment_filename) continue; codec = ost->st->codec;//输出流的编解码器结构 icodec = ist->st->codec;//输入流的编解码器结构 //先把能复制的复制一下 ost->st->disposition = ist->st->disposition; codec->bits_per_raw_sample = icodec->bits_per_raw_sample; codec->chroma_sample_location = icodec->chroma_sample_location; //如果只是复制一个流(不用解码后再编码),则把输入流的编码参数直接复制给输出流 //此时是不需要解码也不需要编码的,所以不需打开解码器和编码器 if (ost->stream_copy) { //计算输出流的编解码器的extradata的大小,然后分配容纳extradata的缓冲 //然后把输入流的编解码器的extradata复制到输出流的编解码器中 uint64_t extra_size = (uint64_t) icodec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; if (extra_size > INT_MAX) { return AVERROR(EINVAL); } /* if stream_copy is selected, no need to decode or encode */ codec->codec_id = icodec->codec_id; codec->codec_type = icodec->codec_type; if (!codec->codec_tag){ if (!oc->oformat->codec_tag ||av_codec_get_id(oc->oformat->codec_tag,icodec->codec_tag) == codec->codec_id ||av_codec_get_tag(oc->oformat->codec_tag,icodec->codec_id) <= 0) codec->codec_tag = icodec->codec_tag; } codec->bit_rate = icodec->bit_rate; codec->rc_max_rate = icodec->rc_max_rate; codec->rc_buffer_size = icodec->rc_buffer_size; codec->extradata = av_mallocz(extra_size); if (!codec->extradata){ return AVERROR(ENOMEM); } memcpy(codec->extradata, icodec->extradata, icodec->extradata_size); codec->extradata_size = icodec->extradata_size; //重新鼓捣一下time base(这家伙就是帧率) codec->time_base = ist->st->time_base; //如果输出文件是avi,做一点特殊处理 if (!strcmp(oc->oformat->name, "avi")) { if (copy_tb < 0 && av_q2d(icodec->time_base) * icodec->ticks_per_frame > 2 * av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0 / 500 || copy_tb == 0) { codec->time_base = icodec->time_base; codec->time_base.num *= icodec->ticks_per_frame; codec->time_base.den *= 2; } } else if (!(oc->oformat->flags & AVFMT_VARIABLE_FPS)) { if (copy_tb < 0 && 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; codec->time_base.num *= icodec->ticks_per_frame; } } //再修正一下帧率 av_reduce(&codec->time_base.num, &codec->time_base.den, codec->time_base.num, codec->time_base.den, INT_MAX); //单独复制各不同媒体自己的编码参数 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_program(1); } codec->channel_layout = icodec->channel_layout; codec->sample_rate = icodec->sample_rate; codec->channels = icodec->channels; codec->frame_size = icodec->frame_size; codec->audio_service_type = icodec->audio_service_type; codec->block_align = icodec->block_align; break; case AVMEDIA_TYPE_VIDEO: //视频的 codec->pix_fmt = icodec->pix_fmt; 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}; } ost->st->avg_frame_rate = ist->st->avg_frame_rate; break; case AVMEDIA_TYPE_SUBTITLE: //字幕的 codec->width = icodec->width; codec->height = icodec->height; break; case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_ATTACHMENT: //??的 break; default: abort(); } } else { //如果不是复制,就麻烦多了 //获取编码器 if (!ost->enc) ost->enc = avcodec_find_encoder(ost->st->codec->codec_id); //因为需要转换,所以既需解码又需编码 ist->decoding_needed = 1; ost->encoding_needed = 1; switch(codec->codec_type) { case AVMEDIA_TYPE_AUDIO: //鼓捣音频编码器的参数,基本上是把一些不合适的参数替换掉 ost->fifo = av_fifo_alloc(1024);//音频数据所在的缓冲 if (!ost->fifo) { return AVERROR(ENOMEM); } //采样率 if (!codec->sample_rate) codec->sample_rate = icodec->sample_rate; choose_sample_rate(ost->st, ost->enc); codec->time_base = (AVRational){1, codec->sample_rate}; //样点格式 if (codec->sample_fmt == AV_SAMPLE_FMT_NONE) codec->sample_fmt = icodec->sample_fmt; choose_sample_fmt(ost->st, ost->enc); //声道 if (ost->audio_channels_mapped) { /* the requested output channel is set to the number of * -map_channel only if no -ac are specified */ if (!codec->channels) { codec->channels = ost->audio_channels_mapped; codec->channel_layout = av_get_default_channel_layout(codec->channels); if (!codec->channel_layout) { av_log(NULL, AV_LOG_FATAL, "Unable to find an appropriate channel layout for requested number of channel\n); exit_program(1); } } /* fill unused channel mapping with -1 (which means a muted * channel in case the number of output channels is bigger * than the number of mapped channel) */ for (j = ost->audio_channels_mapped; j < FF_ARRAY_ELEMS(ost->audio_channels_map); j++) <span> </span>ost->audio_channels_map[j] = -1; }else if (!codec->channels){ codec->channels = icodec->channels; codec->channel_layout = icodec->channel_layout; } if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels) codec->channel_layout = 0; //是否需要重采样 ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1; ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt || codec->channel_layout != icodec->channel_layout; icodec->request_channels = codec->channels; ost->resample_sample_fmt = icodec->sample_fmt; ost->resample_sample_rate = icodec->sample_rate; ost->resample_channels = icodec->channels; break; case AVMEDIA_TYPE_VIDEO: //鼓捣视频编码器的参数,基本上是把一些不合适的参数替换掉 if (codec->pix_fmt == PIX_FMT_NONE) codec->pix_fmt = icodec->pix_fmt; choose_pixel_fmt(ost->st, ost->enc); if (ost->st->codec->pix_fmt == PIX_FMT_NONE){ av_log(NULL, AV_LOG_FATAL, "Video pixel format is unknown, stream cannot be encoded\n"); exit_program(1); } //宽高 if (!codec->width || !codec->height){ codec->width = icodec->width; codec->height = icodec->height; } //视频是否需要重采样 ost->video_resample = codec->width != icodec->width || codec->height != icodec->height || codec->pix_fmt != icodec->pix_fmt; if (ost->video_resample){ codec->bits_per_raw_sample= frame_bits_per_raw_sample; } ost->resample_height = icodec->height; ost->resample_width = icodec->width; ost->resample_pix_fmt = icodec->pix_fmt; //计算帧率 if (!ost->frame_rate.num) ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25,1}; if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) { int idx = av_find_nearest_q_idx(ost->frame_rate,ost->enc->supported_framerates); ost->frame_rate = ost->enc->supported_framerates[idx]; } codec->time_base = (AVRational) {ost->frame_rate.den, ost->frame_rate.num}; if( av_q2d(codec->time_base) < 0.001 && video_sync_method && (video_sync_method==1 || (video_sync_method<0 && ! (oc->oformat->flags & AVFMT_VARIABLE_FPS)))) { av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not effciciently supporting it.\n" "Please consider specifiying a lower framerate, a different muxer or -vsync 2\n"); } <span> </span>for (j = 0; j < ost->forced_kf_count; j++) ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j], AV_TIME_BASE_Q, codec->time_base); break; case AVMEDIA_TYPE_SUBTITLE: break; default: abort(); break; } /* two pass mode */ if (codec->codec_id != CODEC_ID_H264 && (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) { char logfilename[1024]; FILE *f; snprintf(logfilename, sizeof(logfilename), "%s-%d.log", pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX, i); if (codec->flags & CODEC_FLAG_PASS2){ char *logbuffer; size_t logbuffer_size; 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); } codec->stats_in = logbuffer; } if (codec->flags & CODEC_FLAG_PASS1){ f = fopen(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_program(1); } ost->logfile = f; } } } if (codec->codec_type == AVMEDIA_TYPE_VIDEO){ /* maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)*/ //计算编码输出缓冲的大小,计算一个最大值 int size = codec->width * codec->height; bit_buffer_size = FFMAX(bit_buffer_size, 7 * size + 10000); } } //分配编码后数据所在的缓冲 if (!bit_buffer) bit_buffer = av_malloc(bit_buffer_size); if (!bit_buffer){ av_log(NULL, AV_LOG_ERROR, "Cannot allocate %d bytes output buffer\n", bit_buffer_size); return AVERROR(ENOMEM); } //轮循所有输出流,打开每个输出流的编码器 for (i = 0; i < nb_output_streams; i++) { ost = &output_streams[i]; if (ost->encoding_needed){ //当然,只有在需要编码时才打开编码器 AVCodec *codec = ost->enc; AVCodecContext *dec = input_streams[ost->source_index].st->codec; if (!codec) { snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d", avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); ret = AVERROR(EINVAL); goto dump_format; } if (dec->subtitle_header){ ost->st->codec->subtitle_header = av_malloc(dec->subtitle_header_size); if (!ost->st->codec->subtitle_header){ ret = AVERROR(ENOMEM); goto dump_format; } memcpy(ost->st->codec->subtitle_header, dec->subtitle_header,dec->subtitle_header_size); ost->st->codec->subtitle_header_size = dec->subtitle_header_size; } //打开啦 if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) { snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", ost->file_index, ost->index); ret = AVERROR(EINVAL); goto dump_format; } assert_codec_experimental(ost->st->codec, 1); assert_avoptions(ost->opts); if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000) 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; } } //初始化所有的输入流(主要做的就是在需要时打开解码器) for (i = 0; i < nb_input_streams; i++) if ((ret = init_input_stream(i, output_streams, nb_output_streams, error, sizeof(error))) < 0) goto dump_format; /* discard unused programs */ for (i = 0; i < nb_input_files; i++){ InputFile *ifile = &input_files[i]; for (j = 0; j < ifile->ctx->nb_programs; j++){ AVProgram *p = ifile->ctx->programs[j]; int discard = AVDISCARD_ALL; for (k = 0; k < p->nb_stream_indexes; k++){ if (!input_streams[ifile->ist_index + p->stream_index[k]].discard){ discard = AVDISCARD_DEFAULT; break; } } p->discard = discard; } } //打开所有输出文件,写入媒体文件头 for (i = 0; i < nb_output_files; i++){ oc = output_files[i].ctx; oc->interrupt_callback = int_cb; if (avformat_write_header(oc, &output_files[i].opts) < 0){ snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i); ret = AVERROR(EINVAL); goto dump_format; } // assert_avoptions(output_files[i].opts); if (strcmp(oc->oformat->name, "rtp")){ want_sdp = 0; } } return 0; }
相关推荐
cmake编译必须下载这个驱动包:opencv_ffmpeg.dll、opencv_ffmpeg_64.dll、face_landmark_model.dat、2019_win_intel64_20180723_general.zip,用cmake编译自己下载很慢,基本都是失败,需要自己动手下载。
opencv 3.4.3 包含四个文件:opencv_ffmpeg.dll、 opencv_ffmpeg_64.dll、 ffmpeg/ffmpeg_version.cmake、 -ippicv_2017u3_win_ia32_general_20180518.zip 以 md5-文件名 的方式重命名 直接用就可以
FFmpeg是领先的多媒体框架,能够解码,编码, 转码,复用,解复用,流,过滤和播放人类和机器创造的任何东西(ffmpeg transcode aac demo.c)
cmake opencv缺少的opencv_ffmpeg.dll 、 opencv_ffmpeg_64.dll、ffmpeg_version.cmake、face_landmark_model.dat文件;下载后放到文件夹即可。
opencv_ffmpeg.dll opencv_ffmpeg_64.dll ffmpeg_version.cmake boostdesc_bgm.i boostdesc_bgm_bi.i boostdesc_bgm_hd.i boostdesc_binboost_064.i boostdesc_binboost_128.i boostdesc_binboost_256.i boostdesc_...
在OpenCV中,`opencv_videoio_ffmpeg.dll` 和 `opencv_videoio_ffmpeg_64.dll` 是两个关键的动态链接库文件,它们在Windows平台上用于视频I/O操作,特别是通过FFmpeg库与多媒体数据进行交互。 FFmpeg是一个跨平台的...
make[2]: *** [modules/highgui/CMakeFiles/opencv_highgui.dir/src/cap_ffmpeg.o] Error 1 make[1]: *** [modules/highgui/CMakeFiles/opencv_highgui.dir/all] Error 2 make: *** [all] Error 2 解决办法: 通过...
1. **初始化 FFmpeg 库**:首先,你需要通过 `av_register_all()` 和 `avformat_network_init()` 函数注册所有可用的编解码器和网络协议,以便 FFmpeg 可以识别和处理不同的媒体格式。 2. **打开输入文件**:使用 `...
FFmpeg 是一个强大的开源工具套件,用于处理多媒体文件,包括视频、音频转换、流处理等。在Appium自动化测试环境中,FFmpeg 的作用尤为重要,因为它可以帮助处理移动应用中的视频和音频元素,尤其是在进行功能测试...
FFmpeg.AutoGen是一个C#项目,它为FFmpeg库提供了自动化的绑定,使得在C#环境中可以方便地调用FFmpeg的功能。这个项目的核心在于利用FFmpeg的原生API,并通过自动化工具(如SWIG或者SharpGen)生成C#接口,从而在...
FFmpeg 是一个强大的开源工具集,用于处理音视频文件,包括编码、解码、转换、流媒体等众多功能。在Windows环境下,用户通常会遇到编译困难,因此提供预编译版本的 "ffmpeg-4.4-full_build.7z" 文件显得尤为重要。这...
CMake编译OpenCV-4.2.0,需要下载例如opencv_videoio_ffmpeg.dll、opencv_videoio_ffmpeg_64.dll,因为网络原因下载不成功,所以,本人将所有相关文件放到了.cache的文件夹中,只需要利用Cmake选择编译路径和Qt的...
FFmpeg 是一个强大的开源命令行工具,用于处理各种多媒体文件,包括视频、音频转换、流媒体处理等。在这个“ffmpeg-5.0.1-essentials_build(windows)”压缩包中,你将找到适用于 Windows 操作系统的 FFmpeg 基础版本...
"ffmpeg H264解码decode_mb_cavlc函数参数解释" 本文将详细解释ffmpeg H264解码slice的decode_mb_cavlc函数参数,包括mb_skip_run、mb_field_decoding_flag、mb_type、i_mb_type_info、b_mb_type_info、p_mb_type_...
opencv_ffmpeg.dll,opencv_ffmpeg_64.dll,ffmpeg_version.cmake,ippicv_2017u3_win_ia32_general_20170822.zip 我下载 好了分享给大家。
FFmpeg是多媒体处理框架,包含了各种音视频编码、解码、转换、流媒体等功能。在OpenCV库中,FFmpeg被用作视频I/O模块,用于读取、写入和处理视频流。OpenCV 4.2.0版本对CUDA的支持意味着它能够利用NVIDIA GPU的计算...
ffmpeg就这几个函数: ffmpeg_movie: The ffmpeg_movie object provides methods to query and manipulate movies and audio tracks. ffmpeg_frame: The ffmpeg_frame object provides methods to query ...
编译opencv3.2+opencv_contrib-3.2时需要的三个文件,它们的MD5 hash分别如下: ...opencv_ffmpeg_64.dll : a423363a6eb76d362ca6c406c96c8db6 opencv_ffmpeg.dll : f081abd9d6ca7e425d340ce586f9c090
4. **bin**目录:除了ffmpeg.exe,可能还有其他辅助工具,如ffplay(用于播放音视频)、ffprobe(用于分析媒体文件信息)等。 5. **doc**目录:可能包含FFmpeg的文档、教程或者API参考,帮助用户理解和使用FFmpeg。 ...
在FFmpeg中,`av_seek_frame`函数是用于在多媒体流中进行定位的重要工具,它可以让你在解码过程中跳转到特定的时间点。本教程将深入讲解如何使用`av_seek_frame`实现在固定时间开始解码的功能,这对于开发自定义媒体...