在Android平台上合成视频一般使用MediaCodec进行硬编码,使用MediaMuxer进行封装,但是因为MediaMuxer在某些机型上合成的视频在其他手机上播放会出现问题,而且只支持一个音频轨道,因此可以选用FFmpeg来封装编码后的音视频流。

创建FFmpeg AVFormatContext

  1. AVFormatContext*ofmt_ctx=nullptr;
  2. intret=avformat_alloc_output_context2(&ofmt_ctx, nullptr, "mp4", filePath);
  3. AVOutputFormat*ofmt=ofmt_ctx->oformat;
  4. ret=avio_open(&ofmt_ctx->pb, filePath, AVIO_FLAG_WRITE);

添加音视频流

这里以添加h264视频流为例

  1. AVStream*stream=avformat_new_stream(ofmt_ctx, nullptr);
  2. intvideo_stream=stream->index;
  3. AVCodecParameters*codecpar=stream->codecpar;
  4. codecpar->codec_type=AVMEDIA_TYPE_VIDEO;
  5. codecpar->codec_id=AV_CODEC_ID_H264;
  6. codecpar->width=width;
  7. codecpar->height=height;

设置视频流sps和pps

sps和pps能在MediaCodec产生第一帧画面之前获取到,以java MediaCodec异步编码方式为例

  1. @Override
  2. publicvoidonOutputBufferAvailable(@NonNullMediaCodeccodec, intindex, @NonNullMediaCodec.BufferInfoinfo) {
  3. ByteBufferbuffer=encoder.getOutputBuffer(index);
  4. if ((info.flags&MediaCodec.BUFFER_FLAG_CODEC_CONFIG) !=0) {
  5. // 传递 buffer和info.size到native
  6. }
  7. // ...
  8. }
  1. // native获取sps和pps数据地址
  2. uint8_t*data=static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
  3. // 复制给视频流extradata
  4. AVCodecParameters*codecpar=ofmt_ctx->streams[video_stream]->codecpar;
  5. codecpar->extradata= (uint8_t*) av_mallocz(size+AV_INPUT_BUFFER_PADDING_SIZE);
  6. memcpy(codecpar->extradata, data, size);
  7. codecpar->extradata_size=size;

写入视频文件头信息,放在文件开头位置

  1. AVDictionary*dict=nullptr;
  2. av_dict_set(&dict, "movflags", "faststart", 0);
  3. intret=avformat_write_header(ofmt_ctx, &dict);

写入视频流和音频流已编码数据

同样以写入视频流数据为例,️注意视频流和音频流在不同线程写入时需要同步

  1. // onOutputBufferAvailable回调中
  2. booleanisKeyFrame= (info.flags&MediaCodec.BUFFER_FLAG_KEY_FRAME) !=0;
  3. // 传递buffer, info.size, isKeyFrame, info.presentationTimeUs到native
  1. // 获取视频编码数据地址
  2. uint8_t *data = static_cast<uint8_t *>(env->GetDirectBufferAddress(buffer));
  3. AVPacket *packet = av_packet_alloc();
  4. av_init_packet(packet);
  5. packet->stream_index = video_stream;
  6. packet->data = data;
  7. packet->size = size;
  8. packet->pts = av_rescale_q(pts, { 1, 1000000 }, ofmt_ctx->streams[video_stream]->time_base);
  9. if (isKeyFrame) packet->flags |= AV_PKT_FLAG_KEY;
  10. int ret = av_interleaved_write_frame(ofmt_ctx, packet);
  11. av_packet_unref(packet);
  12. av_packet_free(&packet);

结束并关闭文件

至此,整个流程就结束了

  1. av_write_trailer(ofmt_ctx);
  2. avio_closep(&ofmt_ctx->pb);
  3. avformat_free_context(ofmt_ctx);

MediaCodec编码结合FFmpeg封装流的更多相关文章

  1. FFmpeg封装格式处理3-复用例程

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506653.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...

  2. FFmpeg封装格式处理2-解复用例程

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506642.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...

  3. FFmpeg封装格式处理

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506636.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...

  4. WebRTC VideoEngine超详细教程(三)——集成X264编码和ffmpeg解码

    转自:http://blog.csdn.net/nonmarking/article/details/47958395 本系列目前共三篇文章,后续还会更新 WebRTC VideoEngine超详细教 ...

  5. FFmpeg封装格式处理4-转封装例程

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506662.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...

  6. android系统中对ffmpeg封装最好的免费SDK

    android系统中对ffmpeg封装最好的免费SDK; 无论个人还是公司,都免费商用, 欢迎下载. https://github.com/LanSoSdk/LanSoEditor_common 可能 ...

  7. 流媒体测试笔记记录之————阿里云监控、OBS、FFmpeg拉流和推流变化比较记录

    OBS设置视频(512kbps)和音频(128kbps)比特率 阿里云监控结果: 使用FFmpeg拉流到Nginx 服务器测试比特率 第二次测试,修改视频和音频比特率 OBS设置 阿里云监控 Ngin ...

  8. Mediacodec编码后的h264视频出现马赛克问题

    问题:在视频采集后,通过Mediacodec编码生成h264视频文件,播放时出现马赛克较多,无论调整帧率.码率.还是分辨率都不能解决问题 出现问题的原因:编码时传入的时间戳不对.时间戳是视频播放的标准 ...

  9. 音视频处理之FFmpeg封装格式20180510

    一.FFMPEG的封装格式转换器(无编解码) 1.封装格式转换 所谓的封装格式转换,就是在AVI,FLV,MKV,MP4这些格式之间转换(对应.avi,.flv,.mkv,.mp4文件). 需要注意的 ...

随机推荐

  1. wordpress 插件安装 Too Many Requests

    解决办法是在插件界面不直接点击安装/更新,右键新标签页打开链接,会有下载地址. 下载后上传插件即可.

  2. ARMv7-A 架构下的MMU

    ARM架构中MMU的作用主要就是将CPU发出的虚拟地址转换成为物理地址,从实现内核和用户程序和用户程序之间的虚拟地址空间隔离.MMU的主要组成为两部分,其一是内部的TLBs缓存:还有就是转换表装换单元 ...

  3. 016.NET5_MVC_视图组件扩展定制

    视图组件 1. 呈现页面响应的某一部分而不是整个响应 2. 包括在控制器和视图之间发生的关注分类和可测试优势 3.可以具有参数和业务逻辑 4. 通常在页面局部调用 如何自定义视图组件? 1.Razor ...

  4. Object Destructuring Assignment vs Object.assign

    Object Destructuring Assignment vs Object.assign // const params = Object.assign({}, this.$route.par ...

  5. MDN All In One

    MDN All In One https://github.com/mdn/ https://wiki.mozilla.org/MDN MDN 要凉了 https://developer.mozill ...

  6. JSDoc in action

    JSDoc in action JSDoc https://jsdoc.app/index.html https://github.com/jsdoc/jsdoc $ npm -g jsdoc $ n ...

  7. Taro Next

    Taro Next Taro 2.0 https://aotu.io/notes/2020/02/03/taro-next-alpha/index.html Taro Next 的迁移指南 https ...

  8. ES2019 features & ES-Next

    ES2019 features & ES-Next https://github.com/tc39/proposals Object.fromEntries(), trimStart(), t ...

  9. Flutter 将TextField平滑过渡到Text

    import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends State ...

  10. HDFS 01 - HDFS是什么?它的适用场景有哪些?它的架构是什么?

    目录 1.HDFS 是什么 1.1 简单介绍 1.2 发展历史 2.HDFS 应用场景 2.1 适合的应用场景 2.2 不适合的应用场景 3.HDFS 的架构 4.NameNode 和 DataNod ...