之前的设备研发算是告一段落了,最近一直在忙视频监控平台的架构以及实现,想把自己的设备接到自己的平台里,设备上的码流是ps流,要在平台里解码ps流->解码成h264->yuv->rgb最终显示。貌似现在用的最多的解码就是开源的ffmpeg,我也尝试着去研究ffmpeg,当然也只在网上搜搜资料看看如何调用这些,但好像都是些先探测流信息,然后再找解码器那些,但我并不想探测流,因为我已经知道流的格式了(这样也能节省探测时间),经过这段时间的不懈努力,终于搞出来了,现贴出部分代码以及demo
void PSDecode::startup()
{
av_register_all();
}
bool PSDecode::open()
{
m_pCodec = avcodec_find_decoder(CODEC_ID_H264);
if (!m_pCodec)
{
return false;
}
m_pContext = avcodec_alloc_context3(m_pCodec);
if (avcodec_open(m_pContext, m_pCodec) < 0)
{
av_free(m_pContext);
m_pContext = NULL;
m_pCodec = NULL;
}
m_pFrame = avcodec_alloc_frame();
m_pPicture = new AVPicture();
memset(m_pPicture, 0, sizeof(AVPicture));
return true;
}
void PSDecode::close()
{
if (!m_pContext)
{
return;
}
av_free(m_pFrame);
m_pFrame = NULL;
avpicture_free(m_pPicture);
delete m_pPicture;
m_pPicture = NULL;
closeScaleContext();
avcodec_close(m_pContext);
av_free(m_pContext);
m_pContext = NULL;
m_pCodec = NULL;
}
bool PSDecode::inputData(const unsigned char* buffer, size_t length)
{
AVPacket packet;
av_init_packet(&packet);
packet.data = (unsigned char*)buffer;
packet.size = length;
int got_picture = 0;
int ret = avcodec_decode_video2(m_pContext, m_pFrame, &got_picture, &packet);
if (got_picture)
{
updateResolution();
drawFrame();
m_frameCount ++;
}
return (ret >= 0);
}
bool PSDecode::snap(const char* filename)
{
FILE* pFile = fopen(filename, "wb");
if (!pFile)
{
return false;
}
int width = m_pContext->width;
int height = m_pContext->height;
AVPicture picture;
memset(&picture, 0, sizeof(picture));
avpicture_alloc(&picture, PIX_FMT_RGB32, width, height);
SwsContext* pScaleContext = sws_getContext(width, height,
m_pContext->pix_fmt,
width, height, PIX_FMT_RGB32, SWS_BILINEAR, 0, 0, 0);
sws_scale(pScaleContext, m_pFrame->data, m_pFrame->linesize, 0, height,
picture.data, picture.linesize);
sws_freeContext(pScaleContext);
BITMAPINFO bmpInfo;
memset(&bmpInfo, 0, sizeof(bmpInfo));
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = width;
bmpInfo.bmiHeader.biHeight = - height;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biBitCount = 32;
//bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight * bmpInfo.bmiHeader.biBitCount /8;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
int nColors = 0;
BITMAPFILEHEADER hdr;
hdr.bfType = ((WORD) ('M'<<8) |'B'); //is always "RM"
hdr.bfSize = bmpInfo.bmiHeader.biSize + bmpInfo.bmiHeader.biSizeImage + sizeof(hdr);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits=(DWORD) (sizeof(hdr) + bmpInfo.bmiHeader.biSize + nColors * sizeof(RGBQUAD));
fwrite(&hdr,sizeof(hdr), 1, pFile);
bmpInfo.bmiHeader.biHeight = bmpInfo.bmiHeader.biHeight>0?bmpInfo.bmiHeader.biHeight:-bmpInfo.bmiHeader.biHeight;
fwrite(&bmpInfo.bmiHeader, bmpInfo.bmiHeader.biSize, 1, pFile);
int nBytesPerLine = bmpInfo.bmiHeader.biBitCount/8*bmpInfo.bmiHeader.biWidth;
char *pOffset = (char*)picture.data[0] + (bmpInfo.bmiHeader.biHeight-1)*nBytesPerLine;
for (int i=0; i<bmpInfo.bmiHeader.biHeight; i++)
{
fwrite(pOffset, nBytesPerLine, 1, pFile);
pOffset -= nBytesPerLine;
}
fclose(pFile);
avpicture_free(&picture);
return true;
}
下载地址:https://download.csdn.net/download/u010868213/11847014