FFmpeg解码H264视频裸流(直接可用)

1、写在前面

此文章主要包含解码H264视频流数据,主要有以下几点:

1、H264视频帧为Annex B格式,若使用AVCC格式可自行研究;

2、H264视频裸流,非解码视频文件(若有需要我后期可添加这部分代码);

3、支持输出RGB24或YUV420格式,其他可自行修改;

4、FFmpeg官网代码迭代及接口变更较大,代码适应于FFmpeg3.4.2"Cantor"、3.3.7"Hilbert"等版本,较旧接口请看旧版本代码;

2、新版本

FFmpegVideoDecoder.h

#include <libavcodec/avcodec.h>
 
/**
 视频流解码器初始化
 @param ctx 解码参数结构体AVCodecParameters
 @see FFmpeg_H264DecoderInit,此为解码H264视频流
 @return 初始化成功返回0,否则<0
 */
int FFmpeg_VideoDecoderInit(AVCodecParameters *ctx);
 
/**
 H264视频流解码器初始化
 @return 初始化成功返回0,否则<0
 */
int FFmpeg_H264DecoderInit(void);
 
/**
 释放解码器
 @return 初始化成功返回0,否则<0
 */
int FFmpeg_VideoDecoderRelease(void);
 
//return 0:暂未收到解码数据,-1:解码失败,1:解码成功
 
/**
 解码视频流数据
 @param inbuf 视频裸流数据
 @param inbufSize 视频裸流数据大小
 @param framePara 接收帧参数数组:{width,height,linesize1,linesiz2,linesize3}
 @param outRGBBuf 输出RGB数据(若已申请内存)
 @param outYUVBuf 输出YUV数据(若已申请内存)
 @return 成功返回解码数据帧大小,否则<=0
 */
int FFmpeg_H264Decode(unsigned char * inbuf, int inbufSize, int *framePara, unsigned char *outRGBBuf, unsigned char **outYUVBuf);

FFmpegVideoDecoder.c

#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include "FFmpegVideoDecoder.h"
 
struct AVCodecContext *pAVCodecCtx_decoder = NULL;
struct AVCodec *pAVCodec_decoder;
struct AVPacket mAVPacket_decoder;
struct AVFrame *pAVFrame_decoder = NULL;
struct SwsContext* pImageConvertCtx_decoder = NULL;
struct AVFrame *pFrameYUV_decoder = NULL;
 
int FFmpeg_VideoDecoderInit(AVCodecParameters *codecParameters)
{
    if (!codecParameters) {
        CPrintf("Source codec context is NULL.");   //CPrintf需替换为printf
        return -1;
    }
    FFmpeg_VideoDecoderRelease();
    avcodec_register_all();
    
    pAVCodec_decoder = avcodec_find_decoder(codecParameters->codec_id);
    if (!pAVCodec_decoder) {
        CPrintf1("Can not find codec:%d\n", codecParameters->codec_id);
        return -2;
    }
    
    pAVCodecCtx_decoder = avcodec_alloc_context3(pAVCodec_decoder);
    if (!pAVCodecCtx_decoder) {
        CPrintf("Failed to alloc codec context.");
        FFmpeg_VideoDecoderRelease();
        return -3;
    }
   
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ 中使用 FFmpeg 抽取 RTSP 视频的帧,可以按照以下步骤进行: 1. 初始化 FFmpeg 库 ```c++ #include <iostream> extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/imgutils.h> #include <libswscale/swscale.h> } int main() { // 注册 FFmpeg 库中的所有可用的文件格式和编解码器 av_register_all(); return 0; } ``` 2. 打开 RTSP 视频 ```c++ AVFormatContext* format_context = nullptr; AVCodecContext* codec_context = nullptr; AVCodec* codec = nullptr; // 打开 RTSP 视频并读取视频信息 if (avformat_open_input(&format_context, "rtsp://xxx.xxx.xxx.xxx:xxxx/xxx", nullptr, nullptr) != 0) { std::cout << "无法打开 RTSP 视频" << std::endl; return -1; } // 获取视频信息 if (avformat_find_stream_info(format_context, nullptr) < 0) { std::cout << "无法获取视频信息" << std::endl; return -1; } // 查找视频 int video_stream_index = -1; for (int i = 0; i < format_context->nb_streams; i++) { if (format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } } if (video_stream_index == -1) { std::cout << "无法找到视频" << std::endl; return -1; } // 获取视频解码器 codec_context = avcodec_alloc_context3(nullptr); if (!codec_context) { std::cout << "无法分配视频解码器上下文" << std::endl; return -1; } avcodec_parameters_to_context(codec_context, format_context->streams[video_stream_index]->codecpar); codec = avcodec_find_decoder(codec_context->codec_id); if (!codec) { std::cout << "无法找到视频解码器" << std::endl; return -1; } // 打开视频解码器 if (avcodec_open2(codec_context, codec, nullptr) < 0) { std::cout << "无法打开视频解码器" << std::endl; return -1; } ``` 3. 循环读取视频帧 ```c++ AVFrame* frame = nullptr; AVPacket packet; int frame_count = 0; while (av_read_frame(format_context, &packet) >= 0) { // 判断是否为视频包 if (packet.stream_index == video_stream_index) { // 解码视频帧 frame = av_frame_alloc(); int ret = avcodec_send_packet(codec_context, &packet); if (ret < 0) { std::cout << "无法向视频解码器发送数据" << std::endl; break; } while (ret >= 0) { ret = avcodec_receive_frame(codec_context, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cout << "无法解码视频帧" << std::endl; goto end; } // 处理视频帧 std::cout << "第 " << ++frame_count << " 帧" << std::endl; // 释放帧数据 av_frame_unref(frame); } } // 释放视频包 av_packet_unref(&packet); } end: // 释放资源 avcodec_free_context(&codec_context); avformat_close_input(&format_context); ``` 以上是抽取 RTSP 视频帧的基本步骤,具体实现还需要根据实际需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值