嵌入式实践教程--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;
}


相关文章
|
4月前
|
数据采集 大数据 Python
FFmpeg 在爬虫中的应用案例:流数据解码详解
在大数据背景下,网络爬虫与FFmpeg结合,高效采集小红书短视频。需准备FFmpeg、Python及库如Requests和BeautifulSoup。通过设置User-Agent、Cookie及代理IP增强隐蔽性,解析HTML提取视频链接,利用FFmpeg下载并解码视频流。示例代码展示完整流程,强调代理IP对避免封禁的关键作用,助你掌握视频数据采集技巧。
FFmpeg 在爬虫中的应用案例:流数据解码详解
|
4月前
|
语音技术 C语言 Windows
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
|
5月前
|
Linux 编解码 Python
FFmpeg开发笔记(二十四)Linux环境给FFmpeg集成AV1的编解码器
AV1是一种高效免费的视频编码标准,由AOM联盟制定,相比H.265压缩率提升约27%。各大流媒体平台倾向使用AV1。本文介绍了如何在Linux环境下为FFmpeg集成AV1编解码库libaom、libdav1d和libsvtav1。涉及下载源码、配置、编译和安装步骤,包括设置环境变量以启用这三个库。
250 3
FFmpeg开发笔记(二十四)Linux环境给FFmpeg集成AV1的编解码器
|
5月前
|
编解码 Linux 计算机视觉
python 调用ffmpeg使用usb摄像头录制视频,输出h264格式,自动获取摄像头的最佳帧率和最大画面尺寸
使用 Python 调用 FFmpeg 进行 USB 摄像头视频录制,需先确保安装 FFmpeg 和 Python 的 `subprocess` 模块。代码示例展示了如何自动获取摄像头的最佳帧率和最大分辨率,然后录制视频。首先通过 FFmpeg 列出摄像头格式获取信息,解析出帧率和分辨率,选择最优值。之后调用 FFmpeg 命令录制视频,设置帧率、分辨率等参数。注意 `/dev/video0` 是 Linux 的摄像头设备路径,Windows 系统需相应调整。代码中未直接实现自动获取最佳参数,通常需要借助其他库如 OpenCV。
|
6月前
|
编解码 5G Linux
FFmpeg开发笔记(二十一)Windows环境给FFmpeg集成AVS3解码器
AVS3是中国首个8K及5G视频编码标准,相比AVS2和HEVC性能提升约30%。解码器libuavs3d支持8K/60P视频实时解码,兼容多种平台。《FFmpeg开发实战》书中介绍了在Windows环境下如何集成libuavs3d到FFmpeg。集成步骤包括下载源码、使用Visual Studio 2022编译、调整配置、安装库文件和头文件,以及重新配置和编译FFmpeg以启用libuavs3d。
102 0
FFmpeg开发笔记(二十一)Windows环境给FFmpeg集成AVS3解码器
|
6月前
|
编解码 Linux 5G
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
AVS3,中国制定的第三代音视频标准,是首个针对8K和5G的视频编码标准,相比AVS2和HEVC性能提升约30%。uavs3d是AVS3的解码器,支持8K/60P实时解码,且在各平台有优秀表现。要为FFmpeg集成AVS3解码器libuavs3d,需从GitHub下载最新源码,解压后配置、编译和安装。之后,重新配置FFmpeg,启用libuavs3d并编译安装,通过`ffmpeg -version`确认成功集成。
103 0
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
|
25天前
|
Linux 开发工具 Android开发
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
ijkplayer是由Bilibili基于FFmpeg3.4研发并开源的播放器,适用于Android和iOS,支持本地视频及网络流媒体播放。本文详细介绍如何在新版Android Studio中导入并使用ijkplayer库,包括Gradle版本及配置更新、导入编译好的so文件以及添加直播链接播放代码等步骤,帮助开发者顺利进行App调试与开发。更多FFmpeg开发知识可参考《FFmpeg开发实战:从零基础到短视频上线》。
100 2
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
|
1月前
|
编解码 语音技术 内存技术
FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频
《FFmpeg开发实战:从零基础到短视频上线》一书中的“5.1.2 把音频流保存为PCM文件”章节介绍了将媒体文件中的音频流转换为原始PCM音频的方法。示例代码直接保存解码后的PCM数据,保留了原始音频的采样频率、声道数量和采样位数。但在实际应用中,有时需要特定规格的PCM音频。例如,某些语音识别引擎仅接受16位PCM数据,而标准MP3音频通常采用32位采样,因此需将32位MP3音频转换为16位PCM音频。
51 0
FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频
|
1月前
|
XML 开发工具 Android开发
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
ExoPlayer最初是为了解决Android早期MediaPlayer控件对网络视频兼容性差的问题而推出的。现在,Android官方已将其升级并纳入Jetpack的Media3库,使其成为音视频操作的统一引擎。新版ExoPlayer支持多种协议,解决了设备和系统碎片化问题,可在整个Android生态中一致运行。通过修改`build.gradle`文件、布局文件及Activity代码,并添加必要的权限,即可集成并使用ExoPlayer进行网络视频播放。具体步骤包括引入依赖库、配置播放界面、编写播放逻辑以及添加互联网访问权限。
127 1
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
|
1月前
|
Web App开发 安全 程序员
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
多年的互联网寒冬在今年尤为凛冽,坚守安卓开发愈发不易。面对是否转行或学习新技术的迷茫,安卓程序员可从三个方向进阶:1)钻研谷歌新技术,如Kotlin、Flutter、Jetpack等;2)拓展新功能应用,掌握Socket、OpenGL、WebRTC等专业领域技能;3)结合其他行业,如汽车、游戏、安全等,拓宽职业道路。这三个方向各有学习难度和保饭碗指数,助你在安卓开发领域持续成长。
69 1
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势

热门文章

最新文章