FFmpeg4入门13:h264编码为mp4

这篇具有很好参考价值的文章主要介绍了FFmpeg4入门13:h264编码为mp4。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上一篇将yuv源视频文件编码为*.h264的由libx264实现压缩的文件,将源文件从55M编码为620KB,但是h264文件只有视频数据,而且使用范围不太广。那么就需要进一步的封装,在此选用最常用的mp4格式为例。

随便选一个mp4格式文件,用FFmpeg4入门4:解析视频并输出视频信息或者ffprobe查看一下数据。

迈克尔杰克逊的beat it.mp4,输出如下:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'beat.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.73.100
  Duration: 00:05:00.88, start: 0.000000, bitrate: 683 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 852x480, 612 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 64 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

有两条流,一条h264的视频流,一条aac的音频流。现在我们有h264的流,创建一个mp4文件,新建一条流并将h264流插入进去。(暂时没有音频部分)

转换流程图为:

h264->mp4

打开输入文件(h264)

//======================输入部分============================//
//打开输入文件
if(avformat_open_input(&inVFmtCtx,inVFileName,NULL,NULL)<0){
    printf("Cannot open input file.\n");
    break;
}

//查找输入文件中的流
if(avformat_find_stream_info(inVFmtCtx,NULL)<0){
    printf("Cannot find stream info in input file.\n");
    break;
}

//查找视频流在文件中的位置
for(size_t i=0;i<inVFmtCtx->nb_streams;i++){
    if(inVFmtCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){
        inVStreamIndex=(int)i;
        break;
    }
}

AVCodecParameters *codecPara = inVFmtCtx->streams[inVStreamIndex]->codecpar;//输入视频流的编码参数

printf("===============Input information========>\n");
av_dump_format(inVFmtCtx, 0, inVFileName, 0);
printf("===============Input information========<\n");

可以看到和正常打开视频文件一样,或者说除了原始视频文件(yuv格式)其他格式打开代码差不多。

打开输出文件(mp4)

//=====================输出部分=========================//
//打开输出文件并填充格式数据
if(avformat_alloc_output_context2(&outFmtCtx,NULL,NULL,outFileName)<0){
    printf("Cannot alloc output file context.\n");
    break;
}

//打开输出文件并填充数据
if(avio_open(&outFmtCtx->pb,outFileName,AVIO_FLAG_READ_WRITE)<0){
    printf("output file open failed.\n");
    break;
}

//在输出的mp4文件中创建一条视频流
AVStream *outVStream = avformat_new_stream(outFmtCtx,NULL);
if(!outVStream){
    printf("Failed allocating output stream.\n");
    break;
}
outVStream->time_base.den=25;
outVStream->time_base.num=1;
outVStreamIndex=outVStream->index;

//查找编码器
AVCodec *outCodec = avcodec_find_encoder(codecPara->codec_id);
if(outCodec==NULL){
    printf("Cannot find any encoder.\n");
    break;
}

//从输入的h264编码器数据复制一份到输出文件的编码器中
AVCodecContext *outCodecCtx=avcodec_alloc_context3(outCodec);
AVCodecParameters *outCodecPara = outFmtCtx->streams[outVStream->index]->codecpar;
if(avcodec_parameters_copy(outCodecPara,codecPara)<0){
    printf("Cannot copy codec para.\n");
    break;
}
if(avcodec_parameters_to_context(outCodecCtx,outCodecPara)<0){
    printf("Cannot alloc codec ctx from para.\n");
    break;
}
outCodecCtx->time_base.den=25;
outCodecCtx->time_base.num=1;

//打开输出文件需要的编码器
if(avcodec_open2(outCodecCtx,outCodec,NULL)<0){
    printf("Cannot open output codec.\n");
    break;
}

printf("============Output Information=============>\n");
av_dump_format(outFmtCtx,0,outFileName,1);
printf("============Output Information=============<\n");

和上一篇类似。

编码部分

源文件是h264,MP4中的流也是h264,也就是说实际上并没有真正意义上的编码过程。

//写入文件头
if(avformat_write_header(outFmtCtx,NULL)<0){
    printf("Cannot write header to file.\n");
    return -1;
}

//===============编码部分===============//

AVStream *inVStream = inVFmtCtx->streams[inVStreamIndex];
while(av_read_frame(inVFmtCtx,pkt)>=0){//循环读取每一帧直到读完
    if(pkt->stream_index==inVStreamIndex){//确保处理的是视频流
        //FIXME:No PTS (Example: Raw H.264)
        //Simple Write PTS
        //如果当前处理帧的显示时间戳为0或者没有等等不是正常值
        if(pkt->pts==AV_NOPTS_VALUE){
            printf("frame_index:%d\n", frame_index);
            //Write PTS
            AVRational time_base1 = inVStream->time_base;
            //Duration between 2 frames (us)
            int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(inVStream->r_frame_rate);
            //Parameters
            pkt->pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE);
            pkt->dts = pkt->pts;
            pkt->duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE);
            frame_index++;
        }
        //Convert PTS/DTS
        pkt->pts = av_rescale_q_rnd(pkt->pts, inVStream->time_base, outVStream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt->dts = av_rescale_q_rnd(pkt->dts, inVStream->time_base, outVStream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt->duration = av_rescale_q(pkt->duration, inVStream->time_base, outVStream->time_base);
        pkt->pos = -1;
        pkt->stream_index = outVStreamIndex;
        printf("Write 1 Packet. size:%5d\tpts:%ld\n", pkt->size, pkt->pts);
        //Write
        if (av_interleaved_write_frame(outFmtCtx, pkt) < 0) {
            printf("Error muxing packet\n");
            break;
        }
        av_packet_unref(pkt);
    }
}

av_write_trailer(outFmtCtx);

只是一些时间戳方面的处理。

软件输出

===============Input information========&gt;
Input #0, h264, from 'result.h264':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: h264 (High), yuv420p(progressive), 352x288, 25 fps, 25 tbr, 1200k tbn, 50 tbc
===============Input information========&lt;
Cannot open libmwv206dec.so, libmwv206dec.so: cannot open shared object file: No such file or directory
[libx264 @ 0x162cd00] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0x162cd00] profile High, level 1.3
============Output Information=============&gt;
Output #0, mp4, to 'result.mp4':
    Stream #0:0: Video: h264 (High), yuv420p(progressive), 352x288, q=2-31, 25 tbn
============Output Information=============&lt;
OutVIndex=0,pkt.stream_index=0
frame_index==0
Write 1 Packet. size: 6899      pts:0
...共300个

Cannot open libmwv206dec.so ...是deepin linux系统错误。

执行完毕后得到只有视频没有音频的mp4文件。

完整代码在ffmpeg_Binner中13.video_encode_h2642mp4里面。

本文首发于:FFmpeg4入门13:h264编码为mp4文章来源地址https://www.toymoban.com/news/detail-409934.html

到了这里,关于FFmpeg4入门13:h264编码为mp4的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 音视频知识:MPEG-4、H264、MP4、AAC之间的关系

    MPEG-4 一种编码标准。是国际标准化组织 (ISO) 主要针对消费类应用,已经针对运动图像压缩定义的标准。MPEG(Moving Picture Experts Group)标准包括 MPEG1、MPEG2与 MPEG4。 MPEG-4标准目前分为27个部分,统称为ISO/IEC14496国际标准。其中第10部分(ISO/IEC 14496-10)就是熟悉的高级视频编码

    2024年02月14日
    浏览(66)
  • 音视频处理 ffmpeg中级开发 H264编码

    libavcodec/avcodec.h 常用的数据结构 AVCodec 编码器结构体 AVCodecContext 编码器上下文 AVFrame 解码后的帧 结构体内存的分配和释放 av_frame_alloc 申请 av_frame_free() 释放 avcodec_alloc_context3() 创建编码器上下文 avcodec_free_context() 释放编码器上下文 解码步骤 avcodec_find_decoder 查找解码器 avcod

    2024年02月01日
    浏览(82)
  • 【音视频处理】转编码H264 to H265,FFmpeg,代码分享讲解

    大家好,欢迎来到停止重构的频道。 本期我们讨论音视频文件 转编码 ,如将视频H264转H265等。 内容中所提及的 代码都会放在GitHub ,感兴趣的小伙伴可以到GitHub下载。 我们按这样的顺序展开讨论:​ 1、  编码的作用  2、  转编码的工作原理 3、  编解码器安装  4、  示

    2024年02月11日
    浏览(51)
  • 使用FFMPEG分离mp4/flv文件中的264视频和aac音频

    ffmpeg 4.4 一个MP4或flv格式的视频文件 大致分为以下几个简单步骤: 1.使用avformat_open_input 函数打开文件并初始化结构AVFormatContext 2.查找是否存在音频和视频信息 3.构建一个h264_mp4toannexb比特流的过滤器,用来给视频avpaket包添加头信息 4.打开2个输出文件(音频, 视频) 5.循环读

    2024年02月15日
    浏览(45)
  • 使用FFMPEG库封装264视频和acc音频数据到MP4文件中

    ffmepeg 4.4 一段H264的视频文件 一段acc格式的音频文件 1.使用avformat_open_input分别打开视频和音频文件,初始化其AVFormatContext,使用avformat_find_stream_info获取编码器基本信息 2.使用avformat_alloc_output_context2初始化输出的AVFormatContext结构 3.使用函数avformat_new_stream给输出的AVFormatContext结

    2024年02月11日
    浏览(45)
  • 9i物联网浏览器(cef_114.2.120&114.2.100,支持H264视频mp3,mp4)WinForm-CefSharp(5735分支)多媒体版本体验

    更新:2023.6.25 版本: Cef_114.2.110和114.2.100 +chromium- 114.0.5735.134 的32位和64位 说明:支持图片,mp3,mp4(H264)多媒体 测试环境:windows server 2019(其他环境没测,一般问题.NET4.5.2+及vc++运行库问题) 测试网址:www.html5test.com 声明 :本博是交流学习的内容,应用案例定制版浏览器

    2024年02月16日
    浏览(48)
  • OpenCV 报错:FFMPEG: tag 0x34363258/‘X264‘ is not supported with codec id 27 and format ‘mp4 / MP4‘

    首先说一下报错的地方,是在使用VideoWriter保存视频时: 出现如下错误: 经过查找网上资料,发现是cv2.VideoWriter_fourcc()参数存在问题, 解决方法: 将 修改为: 即可完美解决问题。

    2024年02月07日
    浏览(66)
  • FFmpeg将编码后数据保存成mp4

          以下测试代码实现的功能是:持续从内存块中获取原始数据,然后依次进行解码、编码、最后保存成mp4视频文件。       可保存成单个视频文件,也可指定每个视频文件的总帧数,保存多个视频文件。       为了便于查看和修改,这里将可独立的程序段存放在单个函

    2024年02月13日
    浏览(41)
  • 编译FFmpeg4.3.1 、x264并移植到Android

    1、前言 FFmpeg 既是一款音视频编解码工具,同时也是一组音视频编解码开发套件。 2、准备工作 系统:Linux NDK:android-ndk-r21b-linux-x86_64.zip FFmpeg:ffmpeg-snapshot.tar.bz2 x264:x264 3、下载NDK 在linux环境中,使用命令如下:   4、下载FFmpeg 5、下载x264 6、开始编译x264 build_x264_android-v7a

    2024年01月19日
    浏览(39)
  • 视频编码(H264编码)

    基本步骤:    1、打开编码器          2、转换NV12到YUV420,这是因为FFmpeg的x264编码器只支持YUV420          3、准备编码数据AVFrame         创建frame:  创建AVPacket: AVPacket* pck = av_packet_alloc(); 4、H264编码       avcodec_send_frame(#AVCodecContext *avctx#, #const AVFrame *frame#)    

    2024年02月03日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包