基于嵌入式Linux的视频采集系统18-----源程序----decoder.cpp

2019-07-13 04:14发布

本文来自:
http://blog.chinaunix.net/uid-23093301-id-86407.html

#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 ... "));
m_frame_que.resize(10); logtrace(("m_frame_que.size=<%u> ",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 ")); return; } err = pthread_cond_init(&m_pthread_cond,NULL); if(err) { logerror(("CDecoder::CDecoder pthread cond init fail ")); return; }     logtrace(("CDecoder::CDecoder==>> end ok ")); }
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 ",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 ",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... "));          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... "));         goto clean;      }    logtrace(("main:main pkt->data=<%p>,pkt->size=<%d> ok ",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 ");            goto clean;     }    if (avcodec_open(acc, codec) < 0) {            fprintf(stderr, "could not open codec ");            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> ",     PIX_FMT_YUVJ422P,acc->pix_fmt,len1,got_picture));    logtrace(("main:avcodec_decode_video PIX_FMT_YUV420P=<%d> ",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 ");            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... "));
clean: //fprintf(stderr, "CDecoder::try_show==>RROR ocured .... "); 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 ;       }