• 基于FFMPEG的H264视频解码库(流式解码)


           大家都知道ffmpeg的avformat_open_input()函数可以直接打开本地文件或网络流进行解码,我们不用关心分析视频的数据,但是对于加密的视频就无法进行播放,于是就需要对源数据进行处理后,组包成标准的H264格式流,再进行解码。本解码库支持标准的H264格式解码,支持流式解码,不用进行NALU分割,直接将获取到的UDP流送入解码函数即可。  

            H264DecFrame函数的内部我做了缓存组包处理,ffmpeg有av_parser_parse2函数实现这个功能,但是实际使用中发现有问题,包长度总数不对,导致解码出来的视频画面异常,于是自己写了组包的部分。

           本API仅可解码H264裸流,不可以播放封装的格式如MP4、AVI等。

             dll下载:https://download.csdn.net/download/whf227/13108201

            API函数如下:

    * 功能描述:创建解码器
        * @param width:输入图像宽
        * @param height:输入图像高
        * @param picFormat:输入图像格式 0:YUV420
        * @param decThread:输入 解码线程数
        *
        * @return true:成功  false:失败
        */
        bool H264DecCreate(int width, int height, int picFormat = 0, int decThread = 4);
    
    
        /**
        * 功能描述:销毁解码器
        */
        void H264DecDestroy();
    
    
        /**
        * 功能描述:对输入的一段码流进行解码并按帧输出图像
          本函数仅支持流式解码,对于以“00 00 01”为 nalu 分隔符的连续、线性 H.264 码流,
          用户可从任意起始地址、任意长度配置给解码器解码。
          在调用本函数过程中需要注意以下两点:
            −  在解码过程中,用户应该将码流分段,并依次配置给解码器。当用户调用此函
            数,将一段码流配置给解码器之后,应对函数的参数做如下配置:
            pStream=NULL;iStreamLen=0 然后循环调用此函数,直到函数返
            回 H264DEC_NEED_MORE_BITS 时才能再次配置一段新的码流。
            在上述循环调用的过程中,如果函数返回 H264DEC_OK 则表明有一帧图像
            输出,用户必须在循环调用内部及时处理存储在 pDecFrame 中的图像。
            在上述循环调用的过程中,如果函数返回 H264DEC_OK 则表明有一帧图像输
            出,用户必须在循环调用内部及时处理存储在 pDecFrame 中的图像
        * @param pStream:输入 码流起始地址
        * @param streamLen: 输入  码流长度
        * @param pY: 输出 Y分量
        * @param pU: 输出 U分量
        * @param pV: 输出 V分量
        * @param yStride: 输出 Y分量的Stride
        * @param uvStride: 输出 U/V分量的Stride
        * @param flag: 
        *
        * @return 
        */
        int H264DecFrame(unsigned char* pStream, int streamLen, Dec_Frame_S* decFrame, int flag);

    调用方法:

    struct frameStruct
    {
    	UCHAR* data;
    	int length;
    };
    
    
    FILE* h264;
    int decode(void* para)
    { 
    	bool res = false;
    	res = yhDecoder->H264DecCreate(width,height,0);  
    	dec_frame = new Dec_Frame_S;
    	dec_frame->pY = new UCHAR[1920*1080];
    	dec_frame->pU = new UCHAR[1920*1080];
    	dec_frame->pV = new UCHAR[1920*1080];
    	dec_frame->yStride = 0;
    	dec_frame->uvStride = 0;
     
    	while (len>0)
    	{
               char data[1024];
    		   h264 = fopen("F:\\Video\\blackissue.264", "rb");
               int len = (int)fread(data, 1, 1024, h264);
               if(len<=0)
                    break;
                frameStruct* dataFrame = new frameStruct;
                dataFrame->data= data;
                dataFrame->length =1024;
    			result = yhDecoder->H264DecFrame(dataFrame->data, dataFrame>length,dec_frame, 0);			
    			delete[] dataFrame->data;
    			dataFrame->data = NULL;
    			delete dataFrame;
    			dataFrame = NULL;
    	 
    			while (H264DEC_NEED_MORE_BITS != result)  //满足一帧
    			{
    				if (H264DEC_NO_PICTURE == result) /* 解码器中已经没有残留图像 */
    				{
    					break;
    				}
    				if (H264DEC_OK == result) /* 输出一帧图像 */
    				{			
    					canShow = true;	
    					//int ret = sdlDisplay->UpdateSDLWindowYUV(dec_frame->pY, dec_frame->pU, dec_frame->pV, width, height, dec_frame->yStride, dec_frame->uvStride);
    
    					if (!isUDPStream)
    					  SDL_Delay(10);
    				}
    				/* 继续解码剩余H.264码流 */
    				result = yhDecoder->H264DecFrame(NULL, 0, dec_frame, 0);
    			}			
    		 
    	}
     
    
    	yhDecoder->H264DecDestroy();
    	//sdlDisplay->CloseSDL();
    
    	delete[] effictiveData;
    	effictiveData = NULL;
    	delete dec_frame->pY;
    	dec_frame->pY = NULL;
    	delete dec_frame->pU;
    	dec_frame->pU = NULL;
    	delete dec_frame->pV;
    	dec_frame->pV = NULL;
    	delete dec_frame;
    	dec_frame = nullptr;
    	
    	return 0;
    }


         
      

  • 相关阅读:
    授权中的with admin option和with grant option
    CentOS6.2(64bit)下mysql5.6.16主从同步配置
    linux zip命令
    从模版中找到控件的方法和找到样式的方法
    WPF 在事件中绑定命令(不可以在模版中绑定命令)
    WPF: ShowDialog() 切换到其他应用窗口后,再切换回来无法让子窗口总在最上方
    TreeViewItem实现整行选中 (两种用法)
    BitmapImage 读取内存流和显示图片
    IsKeyboardFocused -- 键盘焦点
    WPF中的imagesource 和内存图片的处理
  • 原文地址:https://www.cnblogs.com/thebreeze/p/16036844.html
Copyright © 2020-2023  润新知