嵌入式实践教程--FFmpeg中H264裸流解码为YUV420P原像素

简介: 嵌入式实践教程--FFmpeg中H264裸流解码为YUV420P原像素

一、流程图



image.png

image.png


二、代码



#include <iostream>
using namespace std;
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include<libavutil\imgutils.h>
#include <libavfilter/avfilter.h>
#include <libswscale/swscale.h>
}
AVFormatContext* AFCtx_p;//解封装上下文
AVCodecContext* ACCtx_p;//解码器上下文
AVCodec* codec_p;//解码器
AVFrame* pFrame;
AVFrame* pFrameyuv;
AVPacket* packet;
struct SwsContext* img_convert_ctx;
int videoindex = -1;
int ret, got_picture = 0;
int y_size;
const char path[] = "./res/5min.h264";
int main(int argc, char* argv[])
{
  //打开H264文件,将文件信息存入解封装上下文
  if (avformat_open_input(&AFCtx_p, path, NULL, NULL) != 0)
  {
  cout << "open failed\n" << endl;
  return -1;
  }
  //寻找视频流信息
  if (avformat_find_stream_info(AFCtx_p, NULL) < 0)
  {
  cout << "dtream find failed\n" << endl;
  return -1;
  }
  //dump调试信息
  av_dump_format(AFCtx_p, -1, path, NULL);
  //打开视频并且获取了视频流,设置视频索引默认值
  for (int i = 0; i<AFCtx_p->nb_streams; i++)
  {
  if (AFCtx_p->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
  {
    videoindex = i;
  }
  }
  //如果没有找到视频索引,说明不是一个视频文件
  if (videoindex == -1)
  {
  cout << "not a video\n" << endl;
  return -1;
  }
  //分配解码器上下文空间
  ACCtx_p = avcodec_alloc_context3(NULL);
  //获取编解码器上下文信息
  if (avcodec_parameters_to_context(ACCtx_p, AFCtx_p->streams[videoindex]->codecpar) < 0)
  {
  cout << "copy stream failed\n" << endl;
  return -1;
  }
  //查找解码器
  codec_p = avcodec_find_decoder(ACCtx_p->codec_id);
  if (!codec_p)
  {
  cout << "find decoder error\n" << endl;
  return -1;
  }
  //打开解码器
  if (avcodec_open2(ACCtx_p, codec_p, NULL) != 0)
  {
  cout << "open codec failed" << endl;
  return -1;
  }
  //裁剪图像
  img_convert_ctx = sws_getContext(ACCtx_p->width, ACCtx_p->height,
  ACCtx_p->pix_fmt,
  ACCtx_p->width, ACCtx_p->height,AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);
  if (!img_convert_ctx)
  {
  cout << "get swscale context failed\n" << endl;
  return -1;
  }
  packet = av_packet_alloc();
  pFrame = av_frame_alloc();
  pFrameyuv = av_frame_alloc();
  //获取转换后YUV数据的大小
  int video_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, ACCtx_p->width,
  ACCtx_p->height, 1);
  uint8_t* buf = (uint8_t*)av_malloc(video_size);
  av_image_fill_arrays(pFrameyuv->data, pFrameyuv->linesize,
  buf, AV_PIX_FMT_YUV420P, ACCtx_p->width, ACCtx_p->height, 1);
  char errbuf[256] = { 0 };
  FILE* fp_yuv = fopen("out.yuv", "wb+");
  //循环读取帧数据并转换写入
  while (av_read_frame(AFCtx_p, packet) >= 0)
  {
  if (packet->stream_index == videoindex)
  {
    if (avcodec_send_packet(ACCtx_p, packet) != 0)
    {
    cout << "send video stream packet failed\n" << endl;
    return -1;
    }
    if (avcodec_receive_frame(ACCtx_p, pFrame) != 0)
    {
    cout << "receive video frame failed\n" << endl;
    return -1;
    }
    cout << "decoding frame" << ACCtx_p->frame_number << endl;
    sws_scale(img_convert_ctx,
    pFrame->data, pFrame->linesize,
    0, ACCtx_p->height, pFrameyuv->data, pFrameyuv->linesize);
    y_size = ACCtx_p->width * ACCtx_p->height;
    fwrite(pFrameyuv->data[0], 1, y_size, fp_yuv);//Y
    fwrite(pFrameyuv->data[1], 1, y_size/4, fp_yuv);//U
    fwrite(pFrameyuv->data[2], 1, y_size/4, fp_yuv);//V
  }
  }
  fclose(fp_yuv);
  av_free(buf);
  av_frame_free(&pFrame);
  av_frame_free(&pFrameyuv);
  av_packet_free(&packet);
  sws_freeContext(img_convert_ctx);
  avcodec_free_context(&ACCtx_p);
  avformat_close_input(&AFCtx_p);
  avformat_free_context(AFCtx_p);
  return 1;
}


相关文章
|
7月前
|
数据采集 大数据 Python
FFmpeg 在爬虫中的应用案例:流数据解码详解
在大数据背景下,网络爬虫与FFmpeg结合,高效采集小红书短视频。需准备FFmpeg、Python及库如Requests和BeautifulSoup。通过设置User-Agent、Cookie及代理IP增强隐蔽性,解析HTML提取视频链接,利用FFmpeg下载并解码视频流。示例代码展示完整流程,强调代理IP对避免封禁的关键作用,助你掌握视频数据采集技巧。
104 7
FFmpeg 在爬虫中的应用案例:流数据解码详解
|
7月前
|
语音技术 C语言 Windows
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
|
8月前
|
编解码 Linux 计算机视觉
python 调用ffmpeg使用usb摄像头录制视频,输出h264格式,自动获取摄像头的最佳帧率和最大画面尺寸
使用 Python 调用 FFmpeg 进行 USB 摄像头视频录制,需先确保安装 FFmpeg 和 Python 的 `subprocess` 模块。代码示例展示了如何自动获取摄像头的最佳帧率和最大分辨率,然后录制视频。首先通过 FFmpeg 列出摄像头格式获取信息,解析出帧率和分辨率,选择最优值。之后调用 FFmpeg 命令录制视频,设置帧率、分辨率等参数。注意 `/dev/video0` 是 Linux 的摄像头设备路径,Windows 系统需相应调整。代码中未直接实现自动获取最佳参数,通常需要借助其他库如 OpenCV。
|
8月前
|
Linux 编解码 Python
FFmpeg开发笔记(二十四)Linux环境给FFmpeg集成AV1的编解码器
AV1是一种高效免费的视频编码标准,由AOM联盟制定,相比H.265压缩率提升约27%。各大流媒体平台倾向使用AV1。本文介绍了如何在Linux环境下为FFmpeg集成AV1编解码库libaom、libdav1d和libsvtav1。涉及下载源码、配置、编译和安装步骤,包括设置环境变量以启用这三个库。
355 3
FFmpeg开发笔记(二十四)Linux环境给FFmpeg集成AV1的编解码器
|
9月前
|
编解码 5G Linux
FFmpeg开发笔记(二十一)Windows环境给FFmpeg集成AVS3解码器
AVS3是中国首个8K及5G视频编码标准,相比AVS2和HEVC性能提升约30%。解码器libuavs3d支持8K/60P视频实时解码,兼容多种平台。《FFmpeg开发实战》书中介绍了在Windows环境下如何集成libuavs3d到FFmpeg。集成步骤包括下载源码、使用Visual Studio 2022编译、调整配置、安装库文件和头文件,以及重新配置和编译FFmpeg以启用libuavs3d。
144 0
FFmpeg开发笔记(二十一)Windows环境给FFmpeg集成AVS3解码器
|
9月前
|
编解码 Linux 5G
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
AVS3,中国制定的第三代音视频标准,是首个针对8K和5G的视频编码标准,相比AVS2和HEVC性能提升约30%。uavs3d是AVS3的解码器,支持8K/60P实时解码,且在各平台有优秀表现。要为FFmpeg集成AVS3解码器libuavs3d,需从GitHub下载最新源码,解压后配置、编译和安装。之后,重新配置FFmpeg,启用libuavs3d并编译安装,通过`ffmpeg -version`确认成功集成。
176 0
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
|
4月前
|
Linux 开发工具 Android开发
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
ijkplayer是由Bilibili基于FFmpeg3.4研发并开源的播放器,适用于Android和iOS,支持本地视频及网络流媒体播放。本文详细介绍如何在新版Android Studio中导入并使用ijkplayer库,包括Gradle版本及配置更新、导入编译好的so文件以及添加直播链接播放代码等步骤,帮助开发者顺利进行App调试与开发。更多FFmpeg开发知识可参考《FFmpeg开发实战:从零基础到短视频上线》。
429 2
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
|
4月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
145 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
4月前
|
编解码 语音技术 内存技术
FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频
《FFmpeg开发实战:从零基础到短视频上线》一书中的“5.1.2 把音频流保存为PCM文件”章节介绍了将媒体文件中的音频流转换为原始PCM音频的方法。示例代码直接保存解码后的PCM数据,保留了原始音频的采样频率、声道数量和采样位数。但在实际应用中,有时需要特定规格的PCM音频。例如,某些语音识别引擎仅接受16位PCM数据,而标准MP3音频通常采用32位采样,因此需将32位MP3音频转换为16位PCM音频。
126 0
FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频
|
4月前
|
Android开发 开发者
FFmpeg开发笔记(五十七)使用Media3的Transformer加工视频文件
谷歌推出的Transformer,作为Jetpack Media3架构的一部分,助力开发者实现音视频格式转换与编辑。Media3简化了媒体处理流程,提升了定制性和可靠性。Transformer可用于剪辑、添加滤镜等操作,其示例代码可在指定GitHub仓库中找到。要使用Transformer,需在`build.gradle`中添加相关依赖,并按文档编写处理逻辑,最终完成音视频转换任务。具体步骤包括配置剪辑参数、设置空间效果以及监听转换事件等。
83 0
FFmpeg开发笔记(五十七)使用Media3的Transformer加工视频文件

热门文章

最新文章