注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

_

_

 
 
 

日志

 
 

ffmpeg解码264流  

2013-03-11 19:26:28|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

我的方向:h.264编解码;音视频CODEC;流媒体;directshow+ffmpeg+sdl+live555

2011-05-23 10:21

[收藏]ffmpeg解码264流

VC中使用ffmpeg开发库
要注意连接问题:需要在ffmpeg的.C头文件中加上

view plaincopy to clipboardprint?
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
};
#endif
#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
};
#endif
今天差不多调试了一天的H264实时数据流的解码问题,到了晚上还是没有成功。使用如下方法竟然获取到编码格式为mp3.很奇

怪哦

view plaincopy to clipboardprint?
AVProbeData * pData = new AVProbeData;
ByteIOContext * byteIOCtx = new ByteIOContext;
pData->buf = pRecvBuffer;
pData->buf_size = nDataLen;
pData->filename = "Test";
AVInputFormat * pFMT = NULL;
pFMT = av_probe_input_format(pData, 1);
if(pFMT == NULL)
{
return;
}
init_put_byte(byteIOCtx, pRecvBuffer, nDataLen, 0, this, IOReadVideo, NULL,NULL);
m_pFormatCtontext = NULL;
if(av_open_input_stream(&m_pFormatCtontext,byteIOCtx, "", fmt, NULL) < 0)
{
return;
}
if(av_find_stream_info(m_pFormatCtontext) < 0)
{
return;
}
if(m_pFormatCtontext->nb_streams != 1)
{
return;
}
for(int i = 0; i < m_pFormatCtontext->nb_streams; i++)
{
m_pCodecContext = m_pFormatCtontext->streams[0]->codec;
}
AVProbeData * pData = new AVProbeData;
ByteIOContext * byteIOCtx = new ByteIOContext;
pData->buf = pRecvBuffer;
pData->buf_size = nDataLen;
pData->filename = "Test";
AVInputFormat * pFMT = NULL;
pFMT = av_probe_input_format(pData, 1);
if(pFMT == NULL)
{
return;
}
init_put_byte(byteIOCtx, pRecvBuffer, nDataLen, 0, this, IOReadVideo, NULL,NULL);
m_pFormatCtontext = NULL;
if(av_open_input_stream(&m_pFormatCtontext,byteIOCtx, "", fmt, NULL) < 0)
{
return;
}
if(av_find_stream_info(m_pFormatCtontext) < 0)
{
return;
}
if(m_pFormatCtontext->nb_streams != 1)
{
return;
}
for(int i = 0; i < m_pFormatCtontext->nb_streams; i++)
{
m_pCodecContext = m_pFormatCtontext->streams[0]->codec;
}
用下面的方法获取不到解码后的数据,nGotPicturn总是0

view plaincopy to clipboardprint?
av_register_all();
m_pCodec = avcodec_find_decoder(CODEC_ID_H264);
m_pOutPicture = avcodec_alloc_frame();
m_pCodecContext = avcodec_alloc_context();
if(m_pCodec->capabilities & CODEC_CAP_TRUNCATED)
{
m_pCodecContext->flags|= CODEC_FLAG_TRUNCATED;
}
avcodec_open(m_pCodecContext, m_pCodec);
nUsedLen = avcodec_decode_video(m_pCodecContext, m_pOutPicture, &nGotPicture, pDataBuffer, nUsefulBytes);
av_register_all();
m_pCodec = avcodec_find_decoder(CODEC_ID_H264);
m_pOutPicture = avcodec_alloc_frame();
m_pCodecContext = avcodec_alloc_context();
if(m_pCodec->capabilities & CODEC_CAP_TRUNCATED)
{
m_pCodecContext->flags|= CODEC_FLAG_TRUNCATED;
}
avcodec_open(m_pCodecContext, m_pCodec);

nUsedLen = avcodec_decode_video(m_pCodecContext, m_pOutPicture, &nGotPicture, pDataBuffer, nUsefulBytes);
惨,明天还要继续调

放弃使用这样的方法。直接获取到I帧数据给avcodec_decode_video进行解码

显示H264实时流 收藏
接着上面写,第二天用第二种方法把视频显示出来了,在接收网络数据流后,再加上如下三个字节,就可以正确解码

unsigned char start_code[3] = {0x00, 0x00, 0x01};
memcpy(m_pMediaDataBuffer+m_nUsefulBytes, start_code, 3);

解码后显示方法如下,需要做一个转换(这里化了很上的时间,最开始没有进行如下的转换,一直画不出来)
if (nGotPicture)
{
int size=avpicture_get_size(PIX_FMT_YUV420P, m_pCodecContext->width, m_pCodecContext->height);
if(m_pFillbuf == NULL)
{
m_pFillbuf = av_malloc(size);
}
avpicture_fill(m_pDrawPicture, m_pFillbuf, PIX_FMT_YUV420P, m_pCodecContext->width,

m_pCodecContext->height);
img_convert(m_pDrawPicture, PIX_FMT_YUV420P, m_pOutPicture, m_pCodecContext->pix_fmt, m_pCodecContext-

>width, m_pCodecContext->height);
DrawYUV420P(m_hVideoWnd, m_pDrawPicture);
}

对于上篇写着的两种方法,第二种方法适用一些,第一种方法在接H264时获取AVInputFormat总是错误.

后面几天的工作:

用directshoe filter显示H264实时流。再进行音频的传输功能

最后是音视同步

dll共享全局变量 收藏
dll共享全局变量方法:

#pragma data_seg (".shared")
int g_nPort = 2000;
#pragma data_seg ()

#pragma comment(linker, "/SECTION:.shared,RWS")

G711编解码 收藏
搞语音对讲几天了,播放时声音干扰太大了。拖得时间久有两个原因:

1.每次采样的位数这个值设置的问题。本来是用的采样位数为16,但是服务端那边说用8。导致编解码时8位的始终有杂音。

1.G711编解码的问题:用了一个错误的编解码程序。目前用的编解码代码对于8为始终有杂音

下面把编解码的代码放在这里,16为采集效果很好

view plaincopy to clipboardprint?
//编码
int CG711Decoder::G711_EnCode(unsigned char* pCodecBits, const char* pBuffer, int nBufferSize)
{
short* buffer = (short*)pBuffer;
for(int i=0; i<nBufferSize/2; i++)
{
pCodecBits[i] = encode(buffer[i]);
}
return nBufferSize/2;
}
//解码
int CG711Decoder::G711_Decode(char* pRawData, const unsigned char* pBuffer, int nBufferSize)
{
short *out_data = (short*)pRawData;
for(int i=0; i<nBufferSize; i++)
{
out_data[i] = decode(pBuffer[i]);
}
return nBufferSize*2;
}
#define MAX (32635)
unsigned char CG711Decoder::encode(short pcm)
{
int sign = (pcm & 0x8000) >> 8;
if (sign != 0)
pcm = -pcm;
if (pcm > MAX) pcm = MAX;
int exponent = 7;
int expMask;
for (expMask = 0x4000; (pcm & expMask) == 0
&& exponent>0; exponent--, expMask >>= 1) { }
int mantissa = (pcm >> ((exponent == 0) ? 4 : (exponent + 3))) & 0x0f;
unsigned char alaw = (unsigned char)(sign | exponent << 4 | mantissa);
return (unsigned char)(alaw^0xD5);
}
short CG711Decoder::decode(unsigned char alaw)
{
alaw ^= 0xD5;
int sign = alaw & 0x80;
int exponent = (alaw & 0x70) >> 4;
int data = alaw & 0x0f;
data <<= 4;
data += 8;
if (exponent != 0)
data += 0x100;
if (exponent > 1)
data <<= (exponent - 1);
return (short)(sign == 0 ? data : -data);
}
我的音视同步控制实现 收藏
同步播放时的几种控制处理:
采用外部时钟进行控制,时钟以计数的形式增加,播放线程中使用GetTime()-m_dwStartTime来表示播放时间。
两个时间:m_fRefClock, m_dwStartTime(播放时获取的起始时间) = GetTime()
正常播放:根据外部时钟,比较音,视频的时间戳决定音视频的播放
快进播放:把当前的视频播放时刻保存到m_fRefClock,对于m_dwStartTime重置。在快进后的播放中,时钟需加上

m_fRefClock
快放播放:重置m_dwStartTime,对于重置后获取的时间差进行处理,如*2,需要对(GetTime()-m_dwStartTime)*2,然后加上

m_fRefClock再与音视频的时间戳进行比较。

DWORD GetTime()
{
struct timeval t;
struct _timeb timebuffer;
_ftime( &timebuffer );
t.tv_sec = timebuffer.time;
t.tv_usec = timebuffer.millitm; //ms
return (t.tv_sec * 1000 + t.tv_usec);
}

  评论这张
 
阅读(1850)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017