|
|
|
|
#include <Windows.h>
|
|
|
|
|
#include "decoder_sw.h"
|
|
|
|
|
|
|
|
|
|
void Decoder_Software::ffmpeg_ref_release()
|
|
|
|
|
{
|
|
|
|
|
if (codecctx)
|
|
|
|
|
{
|
|
|
|
|
avcodec_close(codecctx);
|
|
|
|
|
av_free(codecctx);
|
|
|
|
|
codecctx = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (mSrcFrame)
|
|
|
|
|
{
|
|
|
|
|
av_frame_free(&mSrcFrame);
|
|
|
|
|
mSrcFrame = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (mDstFrame)
|
|
|
|
|
{
|
|
|
|
|
av_frame_free(&mDstFrame);
|
|
|
|
|
mDstFrame = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (scxt)
|
|
|
|
|
{
|
|
|
|
|
sws_freeContext(scxt);
|
|
|
|
|
scxt = NULL;
|
|
|
|
|
}
|
|
|
|
|
// av_free_packet(&pkt);
|
|
|
|
|
if (s)
|
|
|
|
|
{
|
|
|
|
|
av_parser_close(s);
|
|
|
|
|
s= NULL;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Decoder_Software::pic_ref_mem_release()
|
|
|
|
|
{
|
|
|
|
|
if (mOutBuf)
|
|
|
|
|
{
|
|
|
|
|
// delete[] mOutBuf;
|
|
|
|
|
av_free(mOutBuf);
|
|
|
|
|
mOutBuf = NULL;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//oPixFmt: 0-YUV 1-RGB 2-BGR
|
|
|
|
|
bool Decoder_Software::decoder_sw_init(int srcWth,int srcHth,int dstWth,int dstHth,int oPixFmt)
|
|
|
|
|
{
|
|
|
|
|
// av_register_all();
|
|
|
|
|
avcodec_register_all();
|
|
|
|
|
|
|
|
|
|
/* find the mpeg1 video decoder */
|
|
|
|
|
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
|
|
|
|
if (!codec)
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
codecctx = avcodec_alloc_context3(codec);
|
|
|
|
|
if (!codecctx)
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(codec->capabilities&CODEC_CAP_TRUNCATED)
|
|
|
|
|
codecctx->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */
|
|
|
|
|
// codecctx->flags2 |= CODEC_FLAG2_FAST;
|
|
|
|
|
|
|
|
|
|
// codecctx->width = img_width;
|
|
|
|
|
// codecctx->height = img_height;
|
|
|
|
|
codecctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
|
|
|
|
|
|
|
|
|
/* open it */
|
|
|
|
|
if (avcodec_open2(codecctx, codec, NULL) < 0)
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dstWth == 0 || dstHth == 0)
|
|
|
|
|
{
|
|
|
|
|
dstWth = srcWth;
|
|
|
|
|
dstHth = srcHth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mSrcWth = srcWth;
|
|
|
|
|
mSrcHth = srcHth;
|
|
|
|
|
mDstWth = dstWth;
|
|
|
|
|
mDstHth = dstHth;
|
|
|
|
|
|
|
|
|
|
// //<2F><><EFBFBD><EFBFBD>YUV<55>ڴ<EFBFBD><DAB4><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// mOutBuf = new uint8_t[mDstWth*mDstHth*3];
|
|
|
|
|
|
|
|
|
|
mPixFmt = oPixFmt;
|
|
|
|
|
|
|
|
|
|
switch (oPixFmt)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
opix_fmt = AV_PIX_FMT_RGB24;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
{
|
|
|
|
|
opix_fmt = AV_PIX_FMT_BGR24;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
opix_fmt = AV_PIX_FMT_YUV420P;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scxt = sws_getContext(mSrcWth,mSrcHth,codecctx->pix_fmt,mDstWth,mDstHth,opix_fmt,SWS_BILINEAR,NULL,NULL,NULL);
|
|
|
|
|
if (!scxt)
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mSrcFrame = av_frame_alloc();
|
|
|
|
|
if (!mSrcFrame)
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mDstFrame = av_frame_alloc();
|
|
|
|
|
if (!mDstFrame)
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mOutBuf = (uint8_t *)av_malloc(av_image_get_buffer_size(opix_fmt, mDstWth, mDstHth, 1));
|
|
|
|
|
av_image_fill_arrays(mDstFrame->data, ((AVPicture *)mDstFrame)->linesize, mOutBuf, opix_fmt, mDstWth, mDstHth, 1);
|
|
|
|
|
|
|
|
|
|
s = av_parser_init(AV_CODEC_ID_H264);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
void Decoder_Software::decoder_sw_release()
|
|
|
|
|
{
|
|
|
|
|
ffmpeg_ref_release();
|
|
|
|
|
pic_ref_mem_release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ʵ<><CAB5>1
|
|
|
|
|
bool YV12_to_RGB24(unsigned char* pYV12, unsigned char* pRGB24, int iWidth, int iHeight)
|
|
|
|
|
{
|
|
|
|
|
if(!pYV12 || !pRGB24)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const long nYLen = long(iHeight * iWidth);
|
|
|
|
|
const int nHfWidth = (iWidth>>1);
|
|
|
|
|
|
|
|
|
|
if(nYLen < 1 || nHfWidth < 1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
unsigned char* yData = pYV12;
|
|
|
|
|
unsigned char* vData = &yData[nYLen];
|
|
|
|
|
unsigned char* uData = &vData[nYLen>>2];
|
|
|
|
|
if(!uData || !vData)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
int rgb[3];
|
|
|
|
|
int i, j, m, n, x, y;
|
|
|
|
|
m = -iWidth;
|
|
|
|
|
n = -nHfWidth;
|
|
|
|
|
for(y = 0; y < iHeight; y++)
|
|
|
|
|
{
|
|
|
|
|
m += iWidth;
|
|
|
|
|
|
|
|
|
|
if(!(y % 2))
|
|
|
|
|
n += nHfWidth;
|
|
|
|
|
|
|
|
|
|
for(x = 0; x < iWidth; x++)
|
|
|
|
|
{
|
|
|
|
|
i = m + x;
|
|
|
|
|
j = n + (x>>1);
|
|
|
|
|
rgb[2] = int(yData[i] + 1.370705 * (vData[j] - 128)); // r<><72><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
rgb[1] = int(yData[i] - 0.698001 * (uData[j] - 128) - 0.703125 * (vData[j] - 128)); // g<><67><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
rgb[0] = int(yData[i] + 1.732446 * (uData[j] - 128)); // b<><62><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
j = nYLen - iWidth - m + x;
|
|
|
|
|
i = (j<<1) + j;
|
|
|
|
|
for(j = 0; j<3; j++)
|
|
|
|
|
{
|
|
|
|
|
if(rgb[j] >= 0 && rgb[j] <= 255)
|
|
|
|
|
{
|
|
|
|
|
pRGB24[i + j] = rgb[j];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pRGB24[i + j] = (rgb[j] < 0) ? 0 : 255;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Decoder_Software::decoder_sw_decoding(unsigned char* in_buf,int in_len)
|
|
|
|
|
{
|
|
|
|
|
if (in_buf == nullptr || in_len <= 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned char* Parser_buf = nullptr;
|
|
|
|
|
int len = 0,size = 0 ;
|
|
|
|
|
while (in_len)
|
|
|
|
|
{
|
|
|
|
|
len = av_parser_parse2(s,codecctx,&Parser_buf,&size,in_buf,in_len,0,0,0);
|
|
|
|
|
in_buf += len;
|
|
|
|
|
in_len -= len;
|
|
|
|
|
if (size)
|
|
|
|
|
{
|
|
|
|
|
av_init_packet(&pkt);//<2F><><EFBFBD><EFBFBD><EFBFBD>ٴγ<D9B4>ʼ<EFBFBD><CABC>
|
|
|
|
|
pkt.data = Parser_buf;
|
|
|
|
|
pkt.size = size;
|
|
|
|
|
int got_picture = 0;
|
|
|
|
|
int ret = avcodec_decode_video2(codecctx,mSrcFrame,&got_picture,&pkt);
|
|
|
|
|
if (got_picture > 0 && ret > 0)
|
|
|
|
|
{
|
|
|
|
|
//callback
|
|
|
|
|
if (decodingCallback > 0)
|
|
|
|
|
{
|
|
|
|
|
if (opix_fmt == AV_PIX_FMT_RGB24 || opix_fmt == AV_PIX_FMT_BGR24)
|
|
|
|
|
{
|
|
|
|
|
//<2F><>תyuv
|
|
|
|
|
mSrcFrame->data[0] += mSrcFrame->linesize[0]*(mSrcHth -1);
|
|
|
|
|
mSrcFrame->linesize[0] *= -1;
|
|
|
|
|
mSrcFrame->data[1] += mSrcFrame->linesize[1]*(mSrcHth/2 -1);
|
|
|
|
|
mSrcFrame->linesize[1] *= -1;
|
|
|
|
|
mSrcFrame->data[2] += mSrcFrame->linesize[2]*(mSrcHth/2 -1);
|
|
|
|
|
mSrcFrame->linesize[2] *= -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//<2F><>yuvת<76><D7AA>Ϊbgr
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
int ret = sws_scale(scxt,
|
|
|
|
|
mSrcFrame->data,
|
|
|
|
|
mSrcFrame->linesize,
|
|
|
|
|
0,
|
|
|
|
|
mSrcHth,
|
|
|
|
|
mDstFrame->data,
|
|
|
|
|
mDstFrame->linesize);
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
int error = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decodingCallback(mOutBuf,mDstWth,mDstHth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|