http://www.chinavideo.org/archiver/?tid-14008.html

关于实时编码解码问题  请教  分享一个编码代码 H264

首先分享一个编码代码使用的是X264  core 122版本 [code]
H264EncWrapper::~H264EncWrapper()
{
        Destroy();
}

int H264EncWrapper::Initialize(int iWidth, int iHeight, int iRateBit, int iFps)
{
    m_param.i_fps_num = iFps;
    m_param.i_fps_den = 1;
    m_param.rc.i_bitrate = iRateBit;
        m_param.rc.i_vbv_max_bitrate=128;
        m_param.i_threads = X264_THREADS_AUTO;
        m_param.i_width = iWidth;
        m_param.i_height = iHeight;
        m_param.i_bframe=0;
        m_param.i_frame_reference=3;
        m_param.rc.i_rc_method=X264_RC_ABR;//X264_RC_CQP ;
        m_param.i_csp = X264_CSP_I420;
        m_param.b_visualize=1;

m_param.b_cabac =0;    
        m_param.b_interlaced=0;
        m_param.i_level_idc=21;
        m_param.i_keyint_max=m_param.i_fps_num*1.5;
        m_param.i_keyint_min=1;

m_param.pf_log = NULL; //x264log;
        m_param.p_log_private = NULL;
        m_param.i_log_level=X264_LOG_NONE;

//m_param.i_keyint_max = 8;
    //m_param.i_keyint_min = 4;

/* 根据输入参数param初始化总结构 x264_t *h     */
    if( ( m_h = x264_encoder_open( &m_param) ) == NULL )
    {
        fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
        return -1;
    }

int i_nal;
        if(x264_encoder_headers( m_h, &m_headers, &i_nal )<0)
        {
                fprintf( stderr, "x264 [error]: x264_encoder_headers failed\n" );
                return -1;
        }

x264_picture_alloc( &m_pic, X264_CSP_I420, m_param.i_width, m_param.i_height );
    m_pic.i_type = X264_TYPE_AUTO;
    m_pic.i_qpplus1 = 0;
   
    return 0;
}

int H264EncWrapper::Destroy()
{
        x264_picture_clean( &m_pic );
        x264_encoder_close(m_h);

return 0;
}

//编码
int H264EncWrapper::Encode(unsigned char* szYUVFrame, unsigned char * pOutputBuffer)
{
        m_pic.img.i_plane = 3;
        m_pic.img.plane[0] = szYUVFrame;
        m_pic.img.plane[1] = szYUVFrame + m_param.i_width * m_param.i_height;
        m_pic.img.plane[2] = (unsigned char *)m_pic.img.plane[1] +  m_param.i_width * m_param.i_height / 4;
        m_pic.img.plane[3] = 0;
   
    m_pic.i_pts = (int64_t)m_iFrameNum * m_param.i_fps_den;

x264_picture_t pic_out;
    x264_nal_t *nal;
    int i_nal, i; // nal的个数

if( x264_encoder_encode( m_h, &nal, &i_nal, &m_pic, &pic_out ) < 0 )
    {
        fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" );
        return -1;
    }

if(i_nal==0)
        {
                //m_iFrameNum++;
                return 0;
        }

int result=0;

for( i = 0; i < i_nal; i++ )
        {
                memcpy(pOutputBuffer, nal[i].p_payload, nal[i].i_payload);
                pOutputBuffer += nal[i].i_payload;
                result += nal[i].i_payload;
        }

m_iFrameNum++;
    return result;
}
[/code]

编码出来可以用播放器播放 也可以用ffplay 播放 和 ffmpeg解码

请教一个问题  在我解码的时候 解码几针后出现 avcodec_decode_video2 函数崩溃了
[attach]1780[/attach]

而且出现了这个提示
[attach]1781[/attach]

但我通过软件查看数据流发现有PPS 和 SPS帧   
[attach]1782[/attach]

我用的是最新的ffmpeg库

附上解码部分代码
主函数中:
[code]        avcodec_register_all(); 
        av_register_all();
       
        m_pCodec=avcodec_find_decoder(CODEC_ID_H264); 
        if(m_pCodec==NULL)
        {
                printf("Error avcodec_find_decoder");
                return -1;
        }
       
        m_pCodecContext=avcodec_alloc_context();
        if(m_pCodecContext==NULL)
        {
                printf("Error avcodec_alloc_context");
                return -1;
        }

m_pCodecContext->width = 320;
        m_pCodecContext->height = 240;
        //m_pCodecContext->pix_fmt = PIX_FMT_YUV420P;
        //m_pCodecContext->codec_id  = CODEC_ID_H264;
        m_pCodecContext->pix_fmt = PIX_FMT_YUV420P;
        int iRet = avcodec_open(m_pCodecContext,m_pCodec);

if(iRet<0)
        {
                printf("Error avcodec_open");
                return -1;
        }

m_pFrame=avcodec_alloc_frame();
        if(m_pFrame==NULL)
        {
                printf("Error avcodec_alloc_frame");
                return -1;
        }

m_pFormatCtx=avformat_alloc_context();

if (!m_pFormatCtx)//分配内存失败
        {
                printf("avformat_alloc_context error\n");      
                return -1;    
        }
        m_parser = av_parser_init(CODEC_ID_H264);
        if(!m_parser)
                return -1; [/code]

解码函数:
[code]VCodecContext* m_pCodecContext; 
AVFrame * m_pFrame;
AVFormatContext *m_pFormatCtx;
AVCodecParserContext * m_parser;

static int DecodeFrame(uint8_t *data , int size)
{
        int got_picture=0;
        AVPacket avp;
        av_init_packet(&avp);

int right=0;
        avp.data=data;
        avp.size=size;

int iRet = avcodec_decode_video2(m_pCodecContext,m_pFrame,&got_picture,&avp);

if(iRet>=0)
        {
                if(got_picture)
                {

right++;
                }
        }
       
        return got_picture;
}

static void DecodeVideo(uint8_t * pInBuffer, int size)
{
        int pos=0;
        int64_t pts=AV_NOPTS_VALUE;
        int64_t dts=AV_NOPTS_VALUE;
        do
        {
                uint8_t *pout;
                int pout_len;
                int len= av_parser_parse2(m_parser,m_pCodecContext,&pout,&pout_len,
                        pInBuffer+pos,size-pos,pts,dts,AV_NOPTS_VALUE);

pos +=len;

if(pout_len >0 )
                {
                        DecodeFrame(pout,pout_len);
                }
        } while (pos<size);

if(size<=0)
        {
                while(DecodeFrame(NULL,0));

}

}
[/code]

希望大家能帮帮忙  ,  任何回复都十分感谢  !

louyily 发表于 2012-3-22 02:24 PM

你的数据来源 能不能保证 传入 解码器的 是一个个完整的 nal 单元,我之前做实时编码的时候 发现传入数据如果不是完整帧就有可能出错的,判断一下 nal的头吧

lovesxw 发表于 2012-3-22 02:36 PM

av_parser_parse2 函数不是校验完整吗? 如果完整的话 就会有返回 不完整就会等待输入 ?

louyily 发表于 2012-3-22 03:13 PM

我之前一直没有用 这个parser,是自己对nal 头做下了判断 因为解的数据是udp发过来的,会出现一些错误的包数据

lovesxw 发表于 2012-3-22 04:00 PM

[i=s] 本帖最后由 lovesxw 于 2012-3-22 04:26 PM 编辑 [/i]

我加了一个判断这回 不过还是不对

[code]
/*the return value is the head offset*/
static int findheader(unsigned char* databuf, int len)
{
       
        char aa[320*240*3]={0};
        CopyMemory(aa,databuf,len);
        int offset = 0;
        bool bFind=false;
        for(; offset< len -4; offset++,databuf++)
        {
                if(databuf[0] == 0x00 && databuf[1] == 0x00 && databuf[2] == 0x00 && databuf[3] == 0x01 && databuf[4] == 0x67)
                {       
                        bFind=true;
                        return offset;
                }
                if(databuf[0] == 0x00 && databuf[1] == 0x00 && databuf[2] == 0x00 && databuf[3] == 0x01 && databuf[4] == 0x65)
                {       
                        bFind=true;
                        return offset;
                }
                if(databuf[0] == 0x00 && databuf[1] == 0x00 && databuf[2] == 0x00 && databuf[3] == 0x01 && databuf[4] == 0x68)
                {       
                        bFind=true;
                        return offset;
                }
        }

if(!bFind)
        {
                return -1;
        }
        return offset;
}

static int DecodeFrame(uint8_t *data , int size)
{
        //防止数据错误
        int offset = findheader(data,size);
        if(offset<0)
        {
                printf("Error data \n");
                return 0;
        }
        int got_picture=0;
        AVPacket avp;
        av_init_packet(&avp);

int right=0;
        avp.data=data+offset;
        avp.size=size-offset;

int iRet = avcodec_decode_video2(m_pCodecContext,m_pFrame,&got_picture,&avp);

if(iRet>=0)
        {
                if(got_picture)
                {
                        right++;
                }
        }
       
        return got_picture;
}

static void DecodeVideo(uint8_t * pInBuffer, int size)
{
        int pos=0;
        int64_t pts=AV_NOPTS_VALUE;
        int64_t dts=AV_NOPTS_VALUE;
        do
        {
                uint8_t *pout;
                int pout_len;
                int len= av_parser_parse2(m_parser,m_pCodecContext,&pout,&pout_len,
                        pInBuffer+pos,size-pos,pts,dts,AV_NOPTS_VALUE);

pos +=len;

if(pout_len >0 )
                {
                        DecodeFrame(pout,pout_len);
                }
        } while (pos<size);

if(size<=0)
        {
                while(DecodeFrame(NULL,0));

}

}[/code]

这种判断可以吧?

louyily 发表于 2012-3-22 05:21 PM

会不会是av_parser_parse2的用法问题
看了下 我的解码流程 就是比你多了个av_free_packet(&packet);
:(等晚上 让版主来看看吧

lovesxw 发表于 2012-3-22 05:29 PM

o(︶︿︶)o 唉  不知道版主能不能帮忙。。。     这个函数是释放  好像和功能无关  愁啊

lovesxw 发表于 2012-3-22 09:00 PM

自己解决了   希望大家不要走弯路    原因是我自己编译的ffmpeg有问题 可以直接下载官方提供的 。
最终代码
[code]static int DecodeFrame(uint8_t *data , int size)
{
        int got_picture=0;
        AVPacket avp;
        av_init_packet(&avp);

avp.data=data;
        avp.size=size;

int iRet = avcodec_decode_video2(m_pCodecContext,m_pFrame,&got_picture,&avp);

if(iRet>=0)
        {
                if(got_picture)
                {

FILE * fp;
                        if((fp=fopen("d:/testout.yuv","ab"))==NULL)
                        {
                                printf("cant open the file");
                                exit(0);
                        }
                        for(int i=0; i<m_pCodecContext->height; i++)
                                fwrite(m_pFrame->data[0] + i * m_pFrame->linesize[0], 1, m_pCodecContext->width, fp);
                        for(int i=0; i<m_pCodecContext->height/2; i++)
                                fwrite(m_pFrame->data[1] + i * m_pFrame->linesize[1], 1, m_pCodecContext->width/2, fp);
                        for(int i=0; i<m_pCodecContext->height/2; i++)
                                fwrite(m_pFrame->data[2] + i * m_pFrame->linesize[2], 1, m_pCodecContext->width/2, fp);

fclose(fp);
                }
        }
       
        return got_picture;
}

static void DecodeVideo(uint8_t * pInBuffer, int size)
{
        int pos=0;
        int64_t pts=AV_NOPTS_VALUE;
        int64_t dts=AV_NOPTS_VALUE;
        do
        {
                uint8_t *pout;
                int pout_len;
                int len= av_parser_parse2(m_parser,m_pCodecContext,&pout,&pout_len,
                        pInBuffer+pos,size-pos,pts,dts,AV_NOPTS_VALUE);

pos +=len;

if(pout_len >0 )
                {
                        DecodeFrame(pout,pout_len);
                }
        } while (pos<size);

if(size<=0)
        {
                while(DecodeFrame(NULL,0));

}

}
[/code]

保存为yuv图像  不需要检测header  以为我那个已经保证是完整的包了

lovesxw 发表于 2012-3-22 09:01 PM

对了 忘了free 我就不补充了

niulei20012001 发表于 2012-3-24 03:03 PM

[i=s] 本帖最后由 niulei20012001 于 2012-3-24 03:07 PM 编辑 [/i]

兄弟,我来给你补充完整[code]AVFrame * m_pFrame;

//AVFormatContext *m_pFormatCtx;

AVCodecParserContext * m_parser;

AVCodec *m_pCodec;
AVCodecContext *m_pCodecContext;

//初始化
bool Decode_init(unsigned int width,unsigned int height)
{
  m_pCodec=avcodec_find_decoder(CODEC_ID_H264); 
        if(m_pCodec==NULL)
        {
                printf("Error avcodec_find_decoder");
                return 0;
        }
        m_pCodecContext=avcodec_alloc_context();
        if(m_pCodecContext==NULL)
        {
                printf("Error avcodec_alloc_context");
                return 0;
        }
        m_pCodecContext->width = width;
        m_pCodecContext->height = height;
        //m_pCodecContext->codec_id  = CODEC_ID_H264;
        m_pCodecContext->pix_fmt = PIX_FMT_YUV420P;
        int iRet = avcodec_open(m_pCodecContext,m_pCodec);
        if(iRet<0)
        {
                printf("Error avcodec_open");
                return 0;
        }
        m_pFrame=avcodec_alloc_frame();
        if(m_pFrame==NULL)
        {
               printf("Error avcodec_alloc_frame");
                return 0;
        }
  //下面的内容,示例中没有
        //m_pFormatCtx=avformat_alloc_context();
        //if (!m_pFormatCtx)//分配内存失败
        //{
        //        printf("avformat_alloc_context error\n");      
        //        return 0;    
        //}
        m_parser = av_parser_init(CODEC_ID_H264);
        if(!m_parser)
                return 0;
return 1;
}
//释放
bool Decode_uninit()
{
av_free(m_pFrame);
avcodec_close(m_pCodecContext);
    av_free(m_pCodecContext);
return 1;
}

static int DecodeFrame(uint8_t *data , int size,unsigned char *yuvOutBuffer)
{
        int got_picture=0;
        AVPacket avp;
        av_init_packet(&avp);

avp.data=data;
        avp.size=size;

int iRet = avcodec_decode_video2(m_pCodecContext,m_pFrame,&got_picture,&avp);

if(iRet>=0)
        {
                if(got_picture)
                {

for(int i=0,nDataLen=0;i<3;i++)
                                        {
                                                int nShift=(i==0)?0:1;
                                                PBYTE pYUVData=(PBYTE)m_pFrame->data[i];
                                                for(int j=0;j<(m_pCodecContext->height>>nShift);j++)
                                                {
                                                        memcpy(&yuvOutBuffer[nDataLen],pYUVData,(m_pCodecContext->width>>nShift));
                                                        pYUVData+=m_pFrame->linesize[i];
                                                        nDataLen+=(m_pCodecContext->width>>nShift);
                                                }
                                        }   
                                        /*FILE * fp;
                        if((fp=fopen("d:/testout.yuv","ab"))==NULL)
                        {
                                printf("cant open the file");
                                exit(0);
                        }
                        for(int i=0; i<m_pCodecContext->height; i++)
                                fwrite(m_pFrame->data[0] + i * m_pFrame->linesize[0], 1, m_pCodecContext->width, fp);
                        for(int i=0; i<m_pCodecContext->height/2; i++)
                                fwrite(m_pFrame->data[1] + i * m_pFrame->linesize[1], 1, m_pCodecContext->width/2, fp);
                        for(int i=0; i<m_pCodecContext->height/2; i++)
                                fwrite(m_pFrame->data[2] + i * m_pFrame->linesize[2], 1, m_pCodecContext->width/2, fp);

fclose(fp);*/
                }
        }
       
        return got_picture;
}
//调用入口函数
void DecodeVideo(uint8_t * pInBuffer, int size,unsigned char *yuvOutBuffer)
{
        int pos=0;
        int64_t pts=AV_NOPTS_VALUE;
        int64_t dts=AV_NOPTS_VALUE;
        do
        {
                uint8_t *pout;
                int pout_len;
int len= av_parser_parse2(m_parser,m_pCodecContext,&pout,&pout_len, pInBuffer+pos,size-pos,pts,dts,AV_NOPTS_VALUE);

pos +=len;

if(pout_len >0 )
                {
                        DecodeFrame(pout,pout_len,yuvOutBuffer);
                }
        } while (pos<size);

if(size<=0)
        {
                while(DecodeFrame(NULL,0,yuvOutBuffer));

}

}[/code]

qibo15193 发表于 2012-4-21 04:07 PM

这个代码没问题么?

cbzhaojay 发表于 2012-5-26 03:26 PM

[b]回复 [url=http://bbs.chinavideo.org/redirect.php?goto=findpost&pid=55342&ptid=14008]10#[/url] [i]niulei20012001[/i] [/b]
你好呀,兄弟, DecodeVideo你这个函数入口 传入的 pInBuffer是一个frame数据还是?
我传入了数据格式如下:
h264head sps h264head pps h264head +后面为一帧的数据
解码不成功也 兄弟能帮忙解释下么?

H264 encode and decode相关推荐

  1. 2019年2月26日 Unique Email Addresses、To Lower Case、Encode and Decode TinyURL

    今天开始加快速度,趁着还有空多刷几题,语言换成python提高速度了. 1. Unique Email Addresses 弱题,注意@符号前后的处理方式不同 class Solution(objec ...

  2. python3 的encode 和 decode

    str ----> bytes: encode 编码 bytes----> str: decode 解码 str.encode() bytes.decode() >>> ...

  3. decode函数python在哪里_Python基础知识——encode和decode函数

    以前我们介绍过,Python2.x中默认的编码的基础类型是unicode编码的类型,在Python3.x才转化为基于unicode的字符串. 那么我们在Python2.x的学习中就会遇到各种各样的编码 ...

  4. pythonunicode和str_python的str,unicode对象的encode和decode方法

    python的str,unicode对象的encode和decode方法 python中的str对象其实就是"8-bit string" ,字节字符串,本质上类似java中的byt ...

  5. python中的encode()和decode()函数

    对于很多人来说,python的中字符转码是一件很头疼的事情,本来期望结果输出的是中文,结果来一段像这样\xe4\xbd\xa0\xe5\xa5\xbd像是乱码的字符串. 由于学python没多久,昨天 ...

  6. Python zipfile 文件名称编码 file_name.encode(‘cp437‘).decode(‘gbk‘)

    主要是处理压缩包里的中文,不出现乱码 with zipfile.ZipFile('love.zip', 'r') as zipobj: #读取压缩包for file_name in zipobj.na ...

  7. python str字符串和byte字节流的区别 encode、decode方法的区别

    Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str和b ...

  8. pythonencode_python的encode和decode误读总结

    python的encode和decode误读总结 最近在学Python,对编码有个误解的地方 下面是错误的理解: encode():编码,将对象的编码转换为指定编码格式,按照字面理解,一直以为是其他编 ...

  9. Python字符串的encode与decode研究心得乱码问题解决方法

    Python字符串的encode与decode研究心得乱码问题解决方法 为什么Python使用过程中会出现各式各样的乱码问题,明明是中文字符却显示成"\xe4\xb8\xad\xe6\x96 ...

  10. Python 问题--encode、decode及shell中文输出

    最近在使用python的时候,涉及到中文输出的时候经常会出现乱码的问题,所以就上网搜索了下,参考了 1.Python字符串的encode与decode研究心得乱码问题解决方法: 2.python 中编 ...

最新文章

  1. 3.4 matlab用for语句实现循环结构
  2. vs2015无法打开包括文件:“winapifamily.h”
  3. jpa oracle 传参int类型判空_springboot学习-springboot使用spring-data-jpa操作MySQL数据库...
  4. 如何使用 vSphere Certificate Manager 替换 SSL 证书 (2097936)
  5. c语言数据类型、运算符和表达式
  6. SpringBoot实战(十三):Spring Boot Admin 动态修改日志级别
  7. UVA121 POJ1319 HDU1621 Pipe Fitters【计算几何】
  8. poj2386(简单的dfs/bfs)
  9. MATLAB模式识别基本操作函数解析
  10. 第十六届全国大学智能车竞赛线上国赛部分队伍名单(除东北赛区之外)
  11. 更改绩效管理流程的5个步骤
  12. Jquery点击事件触发多次解决办法
  13. 电热毯亚马逊欧洲站CE认证审核标准解析
  14. SOP:Ubuntu20安装微信
  15. B 站,真香 ! ! !
  16. Android连接SQLServer详细教程(数据库+服务器+客户端),并在微软Azure云上搭建云服务
  17. 【数学问题】利用python求解表达式
  18. 树莓派安装AdGuard Home
  19. ffmpeg视频转动图gif和Webp
  20. python 全栈开发是什么意思_python全栈要学什么

热门文章

  1. 软件测试典型缺陷分析,软件测试缺陷分析方法简介
  2. 小米盒子刷arm linux,最新小米盒子3s刷原生安卓系统图文教程!值得收藏
  3. 服务器启动显示fr 01,X3850X5服务器无法开机故障处理-微码升级
  4. c语言现代程序设计 现代方法_红河分局加强水文现代化新技术、新仪器、新方法的使用和创新...
  5. 2022-3-6 stm32串口通信实例(库函数)-学习笔记
  6. 数模学习——灰色系统理论
  7. 【保姆级手写理解——灰色预测理论以及python实现】
  8. iOS应用程序审核机制
  9. 74系列芯片功能大全
  10. 用二维数组打印杨辉三角