织梦CMS - 轻松建站从此开始!

罗索

调用xvid 实现解码

jackyhwei 发布于 2011-03-02 13:28 点击:次 
使用xvid编解码rtp传输directshow 播放远程视频时开始会出现绿屏但可以看到图像轮廓,在经过几秒后正常
TAG:

 

  1. /////////////////// 
  2. int init_decoder()  
  3.     int ret; 
  4.     xvid_gbl_init_t   xvid_gbl_init; 
  5.     xvid_dec_create_t xvid_dec_create; 
  6.     /* Reset the structure with zeros */ 
  7.     memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init_t)); 
  8.     memset(&xvid_dec_create, 0, sizeof(xvid_dec_create_t)); 
  9.     /*---------------------- 
  10.      * XviD core initialization 
  11.      *---------------------*/ 
  12.     XDIM = 0 ;  
  13.     YDIM = 0 ;  
  14.     FORMAT = 0 ;  
  15.     CSP = XVID_CSP_BGR; 
  16.     BPP = 3; 
  17.      
  18.     dec_handle = NULL ; 
  19.      
  20.     mp4_buffer = NULL ;  
  21.     out_buffer = NULL ;  
  22.     mp4_ptr = NULL ;  
  23.     /* Version */ 
  24.     xvid_gbl_init.version = XVID_VERSION; 
  25.     /* Assembly setting */ 
  26.     xvid_gbl_init.cpu_flags = 0;  // use assembly optimized  
  27.     xvid_gbl_init.debug = 0 ;     // set debug level 0, no debug output  
  28.     xvid_global(NULL, 0, &xvid_gbl_init, NULL);//XVID 初始化 
  29.     /*--------------------- 
  30.      * XviD encoder initialization 
  31.      *--------------------*/ 
  32.     /* Version */ 
  33.     xvid_dec_create.version = XVID_VERSION; 
  34.     /* 
  35.      * Image dimensions -- set to 0, xvidcore will resize when ever it is 
  36.      * needed 
  37.      */ 
  38.     xvid_dec_create.width = 0;//解码后图像的宽度  如果事先已经知道 那么这里就填写 否则设置0 
  39.     xvid_dec_create.height = 0;//解码后图像的高度 如果事先已经知道 那么这里就填写 否则设置0 
  40.     ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL);//创建xvid 解码实例 
  41.     dec_handle = xvid_dec_create.handle;////将创建的句柄 赋值 给 dec_handle 
  42.     return(ret); 
  43. ////////////////////////////////////////////////////////////////// 
  44. int decode_one_frame(unsigned char *istream, unsigned char *ostream, 
  45.  int istream_size, xvid_dec_stats_t *xvid_dec_stats) 
  46.     int ret; 
  47.     xvid_dec_frame_t xvid_dec_frame; 
  48.     /* Reset all structures */ 
  49.     memset(&xvid_dec_frame, 0, sizeof(xvid_dec_frame_t)); 
  50.     memset(xvid_dec_stats, 0, sizeof(xvid_dec_stats_t)); 
  51.     /* Set version */ 
  52.     xvid_dec_frame.version = XVID_VERSION; 
  53.     xvid_dec_stats->version = XVID_VERSION;   
  54.     /* No general flags to set */ 
  55.     xvid_dec_frame.general          = 0; 
  56.     /* Input stream */ 
  57.     xvid_dec_frame.bitstream        = istream;//待解码的数据 
  58.     xvid_dec_frame.length           = istream_size;//待解码数据的长度 
  59.     /* Output frame structure */ 
  60.     xvid_dec_frame.output.plane[0]  = ostream;//解码完成后 存放原始视频流的缓冲区 
  61.     xvid_dec_frame.output.stride[0] = XDIM*BPP;//步长 即一行像素所占的空间大小 
  62.     xvid_dec_frame.output.csp = CSP;//输出时 采用的色场空间 这里 XVID_CSP_BGR 即采用RGB 
  63.     ret = xvid_decore(dec_handle, XVID_DEC_DECODE
  64. , &xvid_dec_frame, xvid_dec_stats);//ret 值 解码前 帧的长度 
  65.     return(ret); 
  66. ///调用方式 
  67. do { 
  68. /* Decode frame */ 
  69. used_bytes = decode_one_frame(mp4_ptr, out_buffer, useful_bytes, &xvid_dec_stats); 
  70. /* Resize image buffer if needed */ 
  71. if(xvid_dec_stats.type == XVID_TYPE_VOL)//如果输入一帧包含 VOL 重新获得 输出图像的宽度和高度 
  72.     /* Check if old buffer is smaller */ 
  73.    if(XDIM*YDIM < xvid_dec_stats.data.vol.width*xvid_dec_stats.data.vol.height)  
  74.    { 
  75.        /* Copy new witdh and new height from the vol structure */ 
  76.        XDIM = xvid_dec_stats.data.vol.width; 
  77.        YDIM = xvid_dec_stats.data.vol.height; 
  78.                      
  79.        /* Free old output buffer*/ 
  80.        if(out_buffer) free(out_buffer); 
  81.        /* Allocate the new buffer */ 
  82. out_buffer = (unsigned char*)malloc(XDIM*YDIM*4);//动态调整 输出流 存储空间的大小 
  83.            if(out_buffer == NULL) 
  84.            goto free_all_memory; 
  85.    } 
  86. /* Update buffer pointers */ 
  87. if(used_bytes > 0) { 
  88.  mp4_ptr += used_bytes; 
  89.  useful_bytes -= used_bytes; 
  90.  } 
  91. while (xvid_dec_stats.type <= 0 && useful_bytes > MIN_USEFUL_BYTES); 

  92.         /* 显示图像信息*/ 
  93. draw_image(out_buffer) ;  

2 Xvid编解码 实践

   关于编码器输入格式设置:

 其中 en->width 图像采集时的宽度(以像素为单位)

  1. switch( input->format ) 
  2.   { 
  3.   case FORMAT_RAW_BGR24: 
  4.    xvid_enc_frame.input.csp = XVID_CSP_BGR; 
  5.    xvid_enc_frame.input.stride[0] = en->width * 3; 
  6.    break
  7.   case FORMAT_RAW_UYVY: 
  8.    xvid_enc_frame.input.csp = XVID_CSP_UYVY; 
  9.    xvid_enc_frame.input.stride[0] = en->width * 2; 
  10.    break
  11.   case FORMAT_RAW_YUY2: 
  12.    xvid_enc_frame.input.csp = XVID_CSP_YUY2; 
  13.    xvid_enc_frame.input.stride[0] = en->width * 2; 
  14.    break
  15.   } 

 解码器输出格式设置:

 

  1. switch( output->format ) 
  2.  { 
  3.  case FORMAT_RAW_BGR24: 
  4.   xvid_dec_frame.output.stride[0] = m_width*3; 
  5.   xvid_dec_frame.output.csp =XVID_CSP_BGR; 
  6.  
  7.   break
  8.   case FORMAT_RAW_YUY2: 
  9.   xvid_dec_frame.output.csp = XVID_CSP_YUY2; 
  10.   xvid_dec_frame.output.stride[0]= en->width * 2; 
  11.   break
  12.  } 

特别注意的是:

在xvid 中stride 步长与 视频格式有密切格式 一旦设置错误导致 编解码异常终止。

xvid使用小技巧:

(1)解决:使用xvid编解码rtp传输directshow 播放远程视频时开始会出现绿屏但可以看到图像轮廓,在经过几秒后正常

很可能的一个原因是 关键帧丢失 方法:

减小关键帧的间隔

  1. /* Maximum key frame interval */ //最大I帧(关键帧)间隔,一般设置成帧数的10倍 
  2. xvid_enc_create.max_key_interval = 1;//(int)-1;    //--default 10s 

(2)(获得编码后 帧长度)

  1. ret = xvid_encore(m_enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame,&xvid_enc_stats); 
  2. m_enc_frame_length=xvid_enc_stats.length;//编码获得的帧长度 

 

(markman101)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201103/10994.html]
本文出处:CSDN博客 作者:markman101
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容