#include "decoder.h"
#include
#include "log.h"
static int sws_flags = SWS_BICUBIC;
CDecoder::CDecoder():cur_process_pos(0),cur_append_pos(0),num_has_append(0)
{
logtrace(("CDecoder::CDecoder==>> begin ...\n"));
m_frame_que.resize(10);
logtrace(("m_frame_que.size=<%u>\n",m_frame_que.size()));
/* must be called before using avcodec lib */
avcodec_init();
avcodec_register_all();
av_register_all();
int err = pthread_mutex_init(&m_mutex,NULL);
if(err)
{
logerror(("CDecoder::CDecoder pthread mutex init fail\n"));
return;
}
err = pthread_cond_init(&m_pthread_cond,NULL);
if(err)
{
logerror(("CDecoder::CDecoder pthread cond init fail\n"));
return;
}
logtrace(("CDecoder::CDecoder==>> end ok\n"));
}
CDecoder::~CDecoder()
{
}
AVFrame * CDecoder::do_alloc_picture(int pix_fmt, int width, int height)
{
AVFrame *picture;
uint8_t *picture_buf;
int size;
picture = avcodec_alloc_frame();
if (!picture)
return NULL;
size = avpicture_get_size(pix_fmt, width, height);
logtrace(("do_alloc_picture:%d \n",size));
picture_buf = (uint8_t*)malloc(size);
if (!picture_buf) {
av_free(picture);
return NULL;
}
avpicture_fill((AVPicture *)picture, picture_buf,
pix_fmt, width, height);
return picture;
}
void CDecoder::push_frame(void* img,int size)
{
pthread_mutex_lock(&m_mutex);
TFrameNode& var_frame = m_frame_que[cur_append_pos];
if(size>DEF_FRAME_SIZE) return;
var_frame.size = size;
memcpy(var_frame.buff,img,size);
var_frame.pkt.data = (uint8_t*)var_frame.buff;
var_frame.pkt.size = size;
cur_append_pos++;
cur_append_pos = cur_append_pos%m_frame_que.size();
if(cur_append_pos == cur_process_pos)
{
num_has_append = cur_append_pos;
cur_process_pos = 0;
}
else
num_has_append ++;
pthread_cond_signal(&m_pthread_cond);
pthread_mutex_unlock(&m_mutex);
}
AVPacket* CDecoder::pop_frame()
{
AVPacket* ptrFrame=NULL;
if(0 == num_has_append) return ptrFrame;
ptrFrame = &(m_frame_que[cur_process_pos]).pkt;
cur_process_pos ++;
cur_process_pos = cur_process_pos % m_frame_que.size();
num_has_append--;
return ptrFrame;
}
char* CDecoder::readall_file(const string& file,int & size)
{
FILE* fptr;
size = 0;
int readnum;
fptr = fopen(file.c_str(),"r");
char* base_buff =(char*) malloc(10844+100);
char* mybuff = base_buff;
do{
readnum = fread(mybuff,1,1,fptr);
mybuff += readnum;
size += readnum;
}while(readnum);
printf("readall_file size=<%d> ok\n",size);
return base_buff;
}
void CDecoder::try_show(AVFrame* dest_frame,int width,int height)
{
int got_picture,len1;
int dst_pix_fmt;
struct SwsContext *img_convert_ctx = NULL;
AVCodecContext *acc =NULL;
AVFrame *frame = NULL;
AVCodec *codec =NULL;
AVPacket *pkt = NULL;//! no need to free
logtrace(("try_show begin...\n"));
pthread_mutex_lock(&m_mutex);
do{
pkt = pop_frame();
if(pkt != NULL){
memcpy(m_convert_buff.buff,pkt->data,pkt->size);
pkt->data =(uint8_t*) m_convert_buff.buff;
}
else{
pthread_cond_wait(&m_pthread_cond, &m_mutex);
pkt = pop_frame();
}
}while( pkt == NULL);
pthread_mutex_unlock (&m_mutex);
if(pkt == NULL)
{
logtrace(("try_show pop_frame none new frame...\n"));
goto clean;
}
logtrace(("main:main pkt->data=<%p>,pkt->size=<%d> ok\n",pkt->data,pkt->size));
frame= avcodec_alloc_frame();
acc= avcodec_alloc_context();
codec = avcodec_find_decoder(CODEC_ID_MJPEG);
if (!codec) {
fprintf(stderr, "codec not found\n");
goto clean;
}
if (avcodec_open(acc, codec) < 0) {
fprintf(stderr, "could not open codec\n");
goto clean;
}
len1 = avcodec_decode_video(acc,
frame, &got_picture,
pkt->data, pkt->size);
logtrace(("main:avcodec_decode_video PIX_FMT_YUVJ422P=<%d>,c->pix_fmt=<%d>, len1=<%d>,got_picture=<%d> \n",
PIX_FMT_YUVJ422P,acc->pix_fmt,len1,got_picture));
logtrace(("main:avcodec_decode_video PIX_FMT_YUV420P=<%d>\n",PIX_FMT_YUV420P));
if(len1<0)
goto clean;
if(got_picture<=0)
goto clean;
dst_pix_fmt = (int)PIX_FMT_YUV420P ;//PIX_FMT_YUV420P;
img_convert_ctx = sws_getCachedContext( img_convert_ctx,
acc->width, acc->height,
acc->pix_fmt,
width, height,
(PixelFormat)dst_pix_fmt, sws_flags, NULL, NULL, NULL);
if (img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context\n");
goto clean;
}
sws_scale(img_convert_ctx, frame->data, frame->linesize,
0, acc->height, dest_frame->data, dest_frame->linesize);
logtrace(("try_show end ok...\n"));
clean:
//fprintf(stderr, "CDecoder::try_show==>RROR ocured ....\n");
if(img_convert_ctx != NULL)
sws_freeContext(img_convert_ctx);
if(acc != NULL)
{
avcodec_close(acc);
av_free(acc);
}
if(frame != NULL)
av_free(frame);
//if(codec !=NULL)
// av_free(codec);
return ;
}