ffmpeg解码h264

1.   首先注册    av_register_all();注册ffmpeg。如有需要可以自己用其它挨批分别注册
2.   用avcodec_alloc_context3函数分配一个解码环境m_av_ctx,并设置    m_av_ctx->codec_type = AVMEDIA_TYPE_VIDEO;m_av_ctx->codec_id = AV_CODEC_ID_H264;
3.   将解码与解码环境(m_av_ctx)关联。使用avcodec_find_decoder找到h264的。
            例如:AVCodec* codec = avcodec_find_decoder(m_av_ctx->codec_id);
      使用avcodec_open2函数将解码器与解码环境关联。
           例如:int ret = avcodec_open2(m_av_ctx,codec,0);
4.   编写OnDecodec 函数,用于解码h264数据。
      int OnDecodec(unsigned char* buf,int len)
    {
    AVPacket packet;
    av_init_packet(&packet);
    packet.size = len;
    packet.data =buf;
    int ret =0;
    int got =0;
    ret = avcodec_decode_video2(m_av_ctx,m_av_frame,&got,&packet);
    if(ret<0)
    {
        return -1;
    }
    if(ret!=len)
    {
        return -1;
    }
    if(!got)
        return -1;
    .....
    //解码成功
    return ret;
  }

5. 将h264数据给OnDecodec函数即可。

以下是相关源码 (解码为yuv420p数据,这里转成了RGB数据)

//
//  FF264Decoder.hpp
//  M51Ios
//
//  Created by mac on 2019/11/28.
//  Copyright © 2019 mac. All rights reserved.
//

#ifndef FF264Decoder_hpp
#define FF264Decoder_hpp

#include <stdio.h>
extern "C" {

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/imgutils.h"
#include "libswscale/swscale.h"
}
class CFF264Decoder
{
    public:
            CFF264Decoder();
            ~CFF264Decoder();
            int OnDecodec(unsigned char* buf,int len);
            unsigned char* GetImgBuf(int &OutWidth,int &OutHeight);
            void OnLock();
            void OnUnLock();
    private:
            AVCodecContext*    m_av_ctx=0;
            AVFrame*           m_av_frame=0;
            void*              m_lock=0;
            int                m_nLastWidth=0;
            int                m_nLastHeight=0;
            struct SwsContext* m_img_convert_ctx=0;
            unsigned char*     m_pConverBuf=0;
            int                m_nConverBufLen=0;
            
};
#endif /* FF264Decoder_hpp */

 

//
//  FF264Decoder.cpp
//  M51Ios
//
//  Created by mac on 2019/11/28.
//  Copyright © 2019 mac. All rights reserved.
//
#include "FF264Decoder.hpp"
#include "sdk51see.h"
CFF264Decoder::CFF264Decoder()
{
   // InitFF();
    m_av_ctx = avcodec_alloc_context3(nullptr);
    m_av_ctx->codec_type=AVMEDIA_TYPE_VIDEO;
    m_av_ctx->codec_id=AV_CODEC_ID_H264;
    m_av_ctx->pix_fmt= AV_PIX_FMT_YUV420P;
    m_av_ctx->extradata = 0;
    m_av_ctx->extradata_size = 0;
    m_av_ctx->thread_count=1;
    m_av_ctx->thread_type = FF_THREAD_SLICE;
    m_av_ctx->opaque = this;
    m_av_ctx->refcounted_frames=1;
    AVCodec* codec = avcodec_find_decoder(m_av_ctx->codec_id);
    int ret = avcodec_open2(m_av_ctx,codec,0);
    if(ret<0)
    {
        printf("open avcodec err ");
    }
    m_av_frame=av_frame_alloc();
    //av_frame_free(&m_);
    m_lock=M51C_NewLock();
    
}
CFF264Decoder::~CFF264Decoder()
{
    M51C_DelLock(m_lock);
    av_frame_free(&m_av_frame);
    avcodec_free_context(&m_av_ctx);
    sws_freeContext(m_img_convert_ctx);
    av_free(m_pConverBuf);
}
int CFF264Decoder::OnDecodec(unsigned char* buf,int len)
{
    
    AVPacket packet;
    av_init_packet(&packet);
    packet.size = len;
    packet.data =buf;
    int ret =0;
    int got =0;
    ret = avcodec_decode_video2(m_av_ctx,m_av_frame,&got,&packet);
    if(ret<0)
    {
        return -1;
    }
    if(ret!=len)
    {
        return -1;
    }
    if(!got)
        return -1;
    printf("av:%d wh:%d-%d\n",len,m_av_frame->width,m_av_frame->height);
    printf("%d-%d-%d\n",len,m_av_frame->linesize[0],
           m_av_frame->linesize[1],
           m_av_frame->linesize[2]);
    
    if(m_av_frame->width!=m_nLastWidth ||
    m_av_frame->height!=m_nLastHeight)
    {
        if(m_img_convert_ctx)
            sws_freeContext(m_img_convert_ctx);
        m_img_convert_ctx =0;
        int needlen= avpicture_get_size(AV_PIX_FMT_RGBA, m_av_frame->width,m_av_frame->height);
        if(m_nConverBufLen < needlen){
            
            M51C_Lock(m_lock);
            if(m_pConverBuf)
                av_free(m_pConverBuf);
            m_pConverBuf=(unsigned char*)av_malloc(needlen);
            m_nConverBufLen  = needlen;
            M51C_UnLock(m_lock);
        }
    }
    m_nLastWidth  = m_av_frame->width;
    m_nLastHeight = m_av_frame->height;
    
    m_img_convert_ctx = sws_getCachedContext(m_img_convert_ctx,
                                             m_nLastWidth,m_nLastHeight,(AVPixelFormat)m_av_frame->format,
                                             m_nLastWidth,m_nLastHeight,AV_PIX_FMT_RGBA,
                                             SWS_FAST_BILINEAR,
                                             0,0,0);
    
    AVPicture pic;
    avpicture_fill(&pic, m_pConverBuf, AV_PIX_FMT_RGBA,m_nLastWidth ,  m_nLastHeight);
    M51C_Lock(m_lock);
    sws_scale(m_img_convert_ctx,
               m_av_frame->data,m_av_frame->linesize,0,m_av_frame->height,
               pic.data,pic.linesize);
    M51C_UnLock(m_lock);
    av_frame_unref(m_av_frame);
    
    return 1;
}
void CFF264Decoder::OnLock()
{
     M51C_Lock(m_lock);
}
void CFF264Decoder::OnUnLock()
{
     M51C_UnLock(m_lock);
}
unsigned char* CFF264Decoder::GetImgBuf(int &OutWidth,int &OutHeight)
{
    OutWidth=m_nLastWidth;
    OutHeight=m_nLastHeight;
    return m_pConverBuf;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值