关于ffmpeg分离mp4视频帧硬解码遇到的问题

ffmpeg使用经验总结 ffmpeg源码的使用过程 阅读详情

    前段时间在WINCE6搞好一阵时间利用ffmpeg分离mp4出来的视频帧送到硬件解码去,但发现不少问题,我用的是三星的S5PC100处理器,想利用三星提供的MFC的API来进行硬解码,但是根本无法解码,根据调试输出的信息,少了信息头数据,上网查找了好久后,发现mp4/mkv/mov/flv封装的h.264,因为为了减少存储,减少了一些头信息,不是标准的ES流,而从av_read_frame出来的码流一般都是完整的一帧数据的

 

      经过研究的ffmpeg的原代码发现,一般视频帧的信息头数据都会保存在AVCodecContext结构中的extradata ,extradata_size的变量中,  如果是MPEG4编码的话,直接把extradata加在经过av_read_frame分离的视频数据帧前面就可以硬解码了,若是H264的话,我是运用如下函数得到标准ES流的.

 #define EINVAL          22
#define ENOMEM          12
#define AV_RB16(x)  ((((const uint8_t*)(x))[0] << 8) | ((const uint8_t*)(x))[1])
#define AV_RB32(x)  ((((const uint8_t*)(x))[0] << 24) | /
 (((const uint8_t*)(x))[1] << 16) | /
 (((const uint8_t*)(x))[2] <<  8) | /
 ((const uint8_t*)(x))[3])

#define AV_RB32(x)  ((((const uint8_t*)(x))[0] << 24) | /
 (((const uint8_t*)(x))[1] << 16) | /
 (((const uint8_t*)(x))[2] <<  8) | /
 ((const uint8_t*)(x))[3])

#define AV_WB32(p, d) do { /
 ((uint8_t*)(p))[3] = (d); /
 ((uint8_t*)(p))[2] = (d)>>8; /
 ((uint8_t*)(p))[1] = (d)>>16; /
 ((uint8_t*)(p))[0] = (d)>>24; } while(0)

 

typedef struct H264BSFContext {
 uint8_t  length_size;
 uint8_t  first_idr;
 uint8_t *sps_pps_data;
 uint32_t size;
} H264BSFContext;

 

static void alloc_and_copy(uint8_t **poutbuf,          int *poutbuf_size,
         const uint8_t *sps_pps, uint32_t sps_pps_size,
         const uint8_t *in,      uint32_t in_size)
{
 uint32_t offset = *poutbuf_size;
 uint8_t nal_header_size =  4;

 *poutbuf_size += sps_pps_size+in_size+nal_header_size;
 *poutbuf = (unsigned char *)av_realloc(*poutbuf, *poutbuf_size);
    if (*poutbuf==NULL)
        return ;
   
 if (sps_pps)
  memcpy(*poutbuf+offset, sps_pps, sps_pps_size);
 memcpy(*poutbuf+sps_pps_size+nal_header_size+offset, in, in_size);
 //if (!offset)
  AV_WB32(*poutbuf+offset+sps_pps_size, 1);
 //else
 //{
 // (*poutbuf+offset+sps_pps_size)[0] = (*poutbuf+offset+sps_pps_size)[1] = 0;
 // (*poutbuf+offset+sps_pps_size)[2] = 1;
 //}
}

static int h264_mp4toannexb_filter(H264BSFContext *ctx,  AVCodecContext *avctx, const char *args,
           uint8_t  **poutbuf, int *poutbuf_size,
           const uint8_t *buf, int      buf_size,
           int keyframe)
{

 uint8_t unit_type;
 uint32_t nal_size, cumul_size = 0;

 /* nothing to filter */
 if (!avctx->extradata || avctx->extradata_size < 6)
 {
  *poutbuf = (uint8_t*) buf;
  *poutbuf_size = buf_size;
  return 0;
 }

 /* retrieve sps and pps NAL units from extradata */
 if (!ctx->sps_pps_data)
 {
  uint16_t unit_size;
  uint32_t total_size = 0;
  uint8_t *out = NULL, unit_nb, sps_done = 0;
  const uint8_t *extradata = avctx->extradata+4;
  static const uint8_t nalu_header[4] = {0, 0, 0, 1};

  /* retrieve length coded size */
  ctx->length_size = (*extradata++ & 0x3) + 1;
  if (ctx->length_size == 3)
   return AVERROR(EINVAL);

  /* retrieve sps and pps unit(s) */
  unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
  if (!unit_nb)
  {
   unit_nb = *extradata++; /* number of pps unit(s) */
   sps_done++;
  }
  while (unit_nb--)
  {
   unit_size = AV_RB16(extradata);
   total_size += unit_size+4;
   if (extradata+2+unit_size > avctx->extradata+avctx->extradata_size)
   {
    av_free(out);
    return AVERROR(EINVAL);
   }
   out = (unsigned char *)av_realloc(out, total_size);
   if (!out)
    return AVERROR(ENOMEM);
   memcpy(out+total_size-unit_size-4, nalu_header, 4);
   memcpy(out+total_size-unit_size,   extradata+2, unit_size);
   extradata += 2+unit_size;

   if (!unit_nb && !sps_done++)
    unit_nb = *extradata++; /* number of pps unit(s) */
  }

  ctx->sps_pps_data = out;
  ctx->size = total_size;
  ctx->first_idr = 1;
  //char str[512]={0};
  //                           memcpy(str, out, total_size);
 }
 *poutbuf_size = 0;
 *poutbuf = NULL;
 do
 {
  if (ctx->length_size == 1)
   nal_size = buf[0];
  else if (ctx->length_size == 2)
   nal_size = AV_RB16(buf);
  else
  {
   nal_size = AV_RB32(buf);

   
  }

  buf += ctx->length_size;
  unit_type = *buf & 0x1f;

  /* prepend only to the first type 5 NAL unit of an IDR picture */
  if ( unit_type != 6 )
  {
   alloc_and_copy(poutbuf, poutbuf_size, ctx->sps_pps_data, ctx->size, buf, nal_size);
   ctx->first_idr = 0;
  }
  //else
  //{
  // alloc_and_copy(poutbuf, poutbuf_size, NULL, 0,  buf, nal_size);
  // if (!ctx->first_idr && unit_type == 1)
  //  ctx->first_idr = 1;
  //}

  buf += nal_size;
  cumul_size += nal_size + ctx->length_size;
 } while (cumul_size < buf_size);

 return 1;
}

 

通过调用 h264_mp4toannexb_filter函数后就可以得到标准的ES流了,先定义一个H264BSFContext变量,然后传给h264_mp4toannexb_filter函数,

如: 

 H264BSFContext *ctx=(H264BSFContext *) malloc(sizeof(H264BSFContext));
  memset(ctx, 0, sizeof(H264BSFContext));

  while(av_read_frame(pFormatCtx, &packet) >= 0)
  {    

       if(packet.stream_index==videoStream)
      { 
 
          unsigned char *lp=NULL;   //输入的指针
           int len;
           h264_mp4toannexb_filter(ctx, pCodecCtx, NULL, &lp, &len, packet.data, packet.size, 1);
           memcpy((LPBYTE)virInBuf, pCodecCtx->extradata, pCodecCtx->extradata_size);

       }

  }

硬件就可能解码了,这个我是在S5PC100测试成功的,如果是S3C6410应该是类似的,如果是avi文件很容易了,通过av_read_frame直接把它送硬件解码器进行解码就行了

基于QT与ffmpeg的RK3576多路视频硬解码方案 视频编解码技术是多媒体处理的核心基础,其中硬件加速解码通过专用芯片显著提升处理效率。以H.264/H.265为代表的视频编码标准结合VDPU等硬件单元,可实现4K@60fps的高性能解码。在边缘计算场景中,采用QT框架与ffmpeg的组合方案,既能利用跨平台GUI优势,又能通过rkmpp等硬件加速接口降低CPU负载。以RK3576开发板为例,其多路视频处理架构设计涉及生产者-消费者模型、帧同步策略和零拷贝优化等关键技术,可广泛应用于智能监控、工业视觉等领域,实现45% CPU占用率的4路1080p视频稳定处 阅读详情

相关推荐

Android 音视频开篇:基础知识(硬解码)

目录 一、Android音视频硬解码篇: 1,音视频基础知识 2,音视频硬解码流程:封装基础解码框架 3,音视频播放:音视频同步 4,音视频解封和封装:生成一个MP4 二、使用OpenGL渲染视频画面篇 1,初步了解OpenGL ES 2,使用OpenGL渲染视频画面 3,OpenGL渲染多视频,实现画中画 4,深入了解OpenGL之EGL 5,OpenGL FBO数据缓冲区 6,Android音视频硬编码:生成一个MP4 三、Android FFmpeg音视频解码篇 1,...

1 1354

FFmpeg转码太慢的解决方案

FFmpeg转码很慢,默认的调用确实如此,其实本身人家是支持多线程的,用命令启用多线程后转码速度就可以大幅提升了。 假设原始指令为: ffmpeg -i movie.mp4 -vf "crop=640:256:0:400" -strict -2 YourCroppedMovie.mp4 那么启用多线程后的指令: ffmpeg -i movie.mp4 -vf "crop=640:256:0:400" -threads 5 -preset ultrafast -strict -2 YourCroppedMo

我不是码农的博客~~~ 1万+

基于 FFmpeg 设计视频播放器 - 图像 GPU 硬解码

鱼弦:公众号:红尘灯塔,优快云博客专家、内容合伙人、新星导师、全站领域优质创作者、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen)GPU 硬解码是指在图形处理单元 (GPU) 上进行视频解码,而不是在 CPU 上进行软解码。基于 FFmpeg 的图像 GPU 硬解码功能使视频播放器能够在支持硬件解码的设备上实现高性能、低功耗的视频播放。它对于播放高分辨率视频和实现流畅的播放体验至关重要。

走向CTO的路上... 594

ffmpeg 视频解码一

前言 ffmpeg的大版本都已经更新到4了,近段时间我也研究了一下,从这篇文章开始,我将写一个系列,阐述一下ffmpeg API的使用。这篇文章为第一篇,就仅仅讲述一下视频解码相关的使用吧(视频解码会写两篇,这为第一篇,分别使用不同的API)。 流程图 代码流程即如流程图所示,下面讲解一下当中部分函数的作用。 av_parser_init 这是一个解析器,我们根据解码器,实例化这个解析器,后面解析数据时使用。 av_parser_parse2 我们从输入文件得到的原始数据(不适用ffmpeg自带的api

qq_35543489的博客 1730

将MP4视频关键帧数据保存成JPEG格式

获取视频文件中的关键帧,并将关键帧数据编码成JPEG格式的文件。

机载电脑与飞控串口通信(实测读取飞控IMU数据)《一、香橙派5max启动串口UART通信与飞控板通信,一次必通!》《二、allspark1与PIX6C通信踩坑及出坑》《三、orinnx载板与飞控通信》

机载电脑与飞控串口通信(实测读取飞控IMU数据)《一、香橙派5max启动串口UART通信与雷迅v5nano飞控板通信,一次必通!》《二、阿木机载电脑allspark1与PIX6C通信踩坑及出坑》,还有如何打开飞控串口以及如何提高飞控IMU频率。

2402_82745259的博客 3469

ffmpeg视频剪辑视频长度问题,视频无声音,视频卡顿问题

在项目中做视频剪辑,合并多个视频为一个视频时,会出现多种坑,如视频无法播放,视频时长不对,视频无声音,视频合并处卡顿等问题

qq_48329942的博客 6805

【OpenClaw 故障排查完全指南】

OpenClaw 故障排查指南摘要 本指南针对OpenClaw 2026.2.26版本常见问题提供解决方案,适用于Windows/Linux/macOS平台。 核心问题及修复方案: 飞书插件连接失败:删除冲突插件或重装OpenClaw Ollama认证错误:设置环境变量OLLAMA_API_KEY="ollama-local" 配置警告:可安全忽略的安全扫描提示 端口占用:查找并终止占用18789端口的进程 插件重复加载:清理重复插件目录 快速修复: 提供一键修复PowerShell脚本

weixin_37572294的博客 1万+

解决ffmpeg生成mp4文件不能正常预览的问题

框架的使用极大的提高了开发效率,让我们能够有更多的精力去关注系统的整体架构和业务需求,而不需要过多的关注一些具体的实现细节,但任何事情都有两面性,如果某个细节出了问题,由于对具体的实现不了解,那么会给我们解决问题带来不少困扰。 下面借用最近遇到的问题分享一个解决问题的思路,我们的会议系统使用ffmpeg生成的mp4文件在windows下不能正常预览,进一步测试还有如下表现:1、在wmp(系统自带播放器)下播放弹出“无法播放此文件”,而使用vlc播放是正常的;2、使用mp4info打开该文件显示“open

pgj007的专栏 7847

小梅哥Xilinx ZYNQ学习笔记2——38译码器

译码器(Decoder)是一种多输入多输出的组合逻辑电路,负责将二进制代码翻译为特定的对象(如逻辑电平等),功能与编码器相反。译码器一般分为通用译码器和数字显示译码器两大类。本设计的是通用译码器。三八译码器,即是 3 种输入状态翻译成 8 种输出状态。1.case开始开始,endcase结束;2.数字声明时,合法的基数格式有 4 中,包括:十进制('d 或 'D),十六进制('h 或 'H),二进制('b 或 'B),八进制('o 或 'O)。数值可指明位宽,也可不指明位宽。

m0_51430584的博客 1636

YOLOV5 自动刷图脚本实战(十五)之如何找到正确的门

DXF是一个2D游戏,我们所看到的人物移动,其实是后面的背景在移动,我们所看到的画面,不过是一个完整背景中的一个镜头视角而已想要正确找到门的坐标,我们需要对不同的地图中的每个房间做一些配置信息。

qq_38892949的博客 2808

ffmpeg使用心得

假日家里没网络,于是把往日的U盘翻出来,看看里面的旧电影,结果发现Macos播放不了rmvb和kvm格式的电影。实在无聊,原本想去外面蹭网装一个新播放器,忽然想起我的mac 装了ffmpeg,于是试着进行转码。 第一版 刚开始不知道怎么做,先百度,按照百度的命令来 ffmpeg -i xx.rmvb xxx,mp4 果然开始转换了,内心狂喜。结果细细一看,转码速度约0.5倍速,如果是2小时的电影,就需要4个小时。而且我的破mac风扇已经开始狂转了,心理感觉好心疼,忍着转完一部,想着要不要用硬件加速试试

i saw you walking in the rain 1692

8.26华为OD机试真题 新系统 - 仓库查询 (Java/Py/C/C++/Js/Go)

8.26华为OD机试真题 新系统 - 仓库查询 (Java/Py/C/C++/Js/Go)

算法大师! 1731

【流媒体】 通过ffmpeg硬解码拉流RTSP并播放

目前RTSP拉流是网络摄像头获取图片数据常用的方法,但通过CPU软解码的方式不仅延时高且十分占用资源,本文提供了一种从网络摄像头RTSP硬解码的拉流的方法,并且提供python代码以便从网络摄像头获取图片进行后续算法处理。

weixin_68880273的博客 9647

SOUL.md 人格定制的 7 个高阶技巧:Hermes Agent 精准控制 AI 行为模式

揭示 SOUL.md 的本质是行为契约而非人格设定,介绍7个围绕边界约束的高阶技巧,包括用上下文锚点(INPUT SCOPE/OUTPUT TARGET/CONSTRAINTS)替代角色描述、动态渲染锚点适配CI流程等,显著降低token消耗与人工review耗时。

weixin_42520239的博客 251

Python爬虫实战:构建高可用静态网页爬虫 - 以 Quotes 网站数据采集为例!

我长期专注 Python 爬虫工程化实战,主理专栏 《Python爬虫实战》:从采集策略到反爬对抗,从数据清洗到分布式调度,持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”,让数据价值真正做到——抓得到、洗得净、用得上。

喵手的博客 461

关于ffmpeg的硬解码

代码功能:打开H264编码格式的.mp4文件,通过硬件设备对MP4文件进行转码。即不占用CPU资源的情况下解析视频

weixin_48691014的博客 2745

基于STM32L4XX 、HAL库的TMC2209-LA-T步进电机驱动器驱动程序应用设计

/ R/W=0 表示写。uint32_t gconf_value = (0 << 0) // I_scale_analog: 禁用,使用UART控制电流。uint32_t ihold_irun = (8 << 0) // 保持电流 8/31 最大值。

PP_Cottage的博客 449

ffmpeg硬解码与软解码的压测对比

ffmpeg硬解码与软解码的压测脚本编写及结果对比分析

weixin_47407737的博客 4011

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

wasm + ffmpeg实现前端截取视频帧功能

有没有那么一种可能,在前端页面处理音视频?例如用户选择一个视频,然后支持他设置视频的任意一帧作为封面,就不用把整一个视频上传到后端处理了。支持mp4/mov/mkv/avi等文件。基本的思想是这样的:使用一个file input让用户选择一个视频文件,然后读取为ArrayBuffer,传给ffmpeg.wasm处理,处理完之后,输出rgb数据画到canvas上或者是转成base64当做img标签的src属性就形成图片了。

yinshipin007的博客 2372

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

ffmpeg实现前端截取视频帧功能和实现web在线转码播放

有没有那么一种可能,在前端页面处理音视频?例如用户选择一个视频,然后支持他设置视频的任意一帧作为封面,就不用把整一个视频上传到后端处理了。支持mp4/mov/mkv/avi等文件。基本的思想是这样的:使用一个file input让用户选择一个视频文件,然后读取为ArrayBuffer,传给ffmpeg.wasm处理,处理完之后,输出rgb数据画到canvas上或者是转成base64当做img标签的src属性就形成图片了。

細水、長流√的专栏 3300

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

FFmpeg 4.2 从入门到精通(二)—— QT 中用 FFmpeg 实现硬解码并使用QImage显示

读取码流中的音频若干帧或者视频一帧,av_read_frame()函数是新型ffmpeg的用法,对 av_read_packet 进行了封装,旧用法之所以被抛弃,就是因为以前获取的数据可能不是完整的,而av_read_frame()保证了视频数据一帧的完整性,使读出的数据总是完整的一帧。为 AVFormatContext 分配空间,打开输入的视频数据并且探测视频的格式,这个函数里面包含了复杂的格式解析与探测算法,可解析的内容包括:视频流、音频流、视频流参数、音频流参数、视频帧索引等。

irainsa的博客 1075

FFmpeg教程(超级详细版)

一、参考资料 通过ffmpeg把图片转换成视频 FFmpeg命令(一)、使用filter_complex命令拼接视频 FFmpeg 视频处理入门教程给新手的 20 多个 FFmpeg 命令示例 FFmpeg命令行转码 ffmpeg 翻译文档 (ffmpeg-all 包含重要组件) FFmpeg Filters Documentation FFmpeg命令行滤镜使用 ffmpeg命令行使用nvidia CUDA scaling高速转分辨率转码(libnpp) FFmpeg—源码编译 FFmpeg常用命令 Li

IT菜鸟 11万+
下一篇: android TD-SCDMA视频电话开发
springlim
博客等级 码龄19年 8粉丝 4原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值