123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- #include "ivh264framedecode.h"
- ivh264framedecode::ivh264framedecode(int framewidth,int frameheight)
- {
- mframeheight = frameheight;
- mframewidth = framewidth;
- int i;
- for(i=0;i<FRAMEDECBUFSIZE;i++)
- {
- mdecbuf[i].mbuf.myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
- mdecbuf[i].mbuf.framewidth = mframewidth;
- mdecbuf[i].mbuf.frameheight = mframeheight;
- }
- mpthread = new std::thread(&ivh264framedecode::threaddecode,this);
- }
- int ivh264framedecode::GetUpdatedIndex()
- {
- if(mvectorupdateindex.size() == 0 )return -1;
- return mvectorupdateindex[0];
- }
- int ivh264framedecode::GetUpdatedIndex(int nwaitms)
- {
- std::unique_lock<std::mutex> lk(mmutex_cvread);
- if(mcvread.wait_for(lk, std::chrono::milliseconds(nwaitms)) == std::cv_status::timeout)
- {
- lk.unlock();
- return -1;
- }
- lk.unlock();
- if(mvectorupdateindex.size()>0)return mvectorupdateindex[0];
- return -1;
- }
- iv::framedecodebuf * ivh264framedecode::LockReadBuff(int nbufindex)
- {
- if(nbufindex < 0)return NULL;
- if(nbufindex >= FRAMEDECBUFSIZE)return NULL;
- mdecbuf[nbufindex].mMutex.lock();
- return &mdecbuf[nbufindex].mbuf;
- }
- void ivh264framedecode::UnlockReadBuff(int nbufindex)
- {
- mdecbuf[nbufindex].mMutex.unlock();
- mmutexstate.lock();
- mvectorupdateindex.erase(mvectorupdateindex.begin());
- mmutexstate.unlock();
- }
- int ivh264framedecode::GetEmptyIndex()
- {
- int i;
- int nindex = -1;
- mmutexstate.lock();
- for(i=0;i<FRAMEDECBUFSIZE;i++)
- {
- int j;
- bool bUsed = false;
- for(j=0;j<(int)(mvectorupdateindex.size());j++)
- {
- if(mvectorupdateindex[j] == i)
- {
- bUsed = true;
- break;
- }
- }
- if(bUsed == false)
- {
- nindex = i;
- break;
- }
- }
- mmutexstate.unlock();
- return nindex;
- }
- iv::framedecodebuf * ivh264framedecode::LockWriteBuff(int nbufindex)
- {
- if(nbufindex < 0)return NULL;
- if(nbufindex >= FRAMEDECBUFSIZE)return NULL;
- mdecbuf[nbufindex].mMutex.lock();
- return &mdecbuf[nbufindex].mbuf;
- }
- void ivh264framedecode::UnlockWriteBuff(int nbufindex)
- {
- mdecbuf[nbufindex].mMutex.unlock();
- mmutexstate.lock();
- mvectorupdateindex.push_back(nbufindex);
- mmutexstate.unlock();
- }
- void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)
- {
- // char buf[1024];
- int ret;
- ret = avcodec_send_packet(dec_ctx, pkt);
- if (ret < 0) {
- fprintf(stderr, "Error sending a packet for decoding\n");
- return;
- }
- while (ret >= 0) {
- ret = avcodec_receive_frame(dec_ctx, frame);
- if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
- return;
- else if (ret < 0) {
- fprintf(stderr, "Error during decoding\n");
- return;
- }
- printf("saving frame %3d\n", dec_ctx->frame_number);
- fflush(stdout);
- /* the picture is allocated by the decoder. no need to
- free it */
- // snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
- // cv::Mat yuvImg;
- // cv::Mat rgbImg(cy, cx,CV_8UC3);
- int index = GetEmptyIndex();
- if(index < 0)
- {
- std::cout<<" no empty buffer used. "<<std::endl;
- break;
- }
- iv::framedecodebuf * pbuf = LockWriteBuff(index);
- if((mframeheight != frame->height)||(mframewidth != frame->width))
- {
- mframeheight = frame->height;
- mframewidth = frame->width;
- pbuf->myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
- pbuf->frameheight = mframeheight;
- pbuf->framewidth = mframewidth;
- std::cout<<"change width to : "<<mframewidth<<" change heigth to: "<<mframeheight<<std::endl;
- }
- int cy = mframeheight;
- int cx = mframewidth;
- memcpy(pbuf->myuvImg.data, frame->data[0], cy*cx);
- memcpy(pbuf->myuvImg.data + cy*cx,frame->data[1],cy*cx/4);
- memcpy(pbuf->myuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
- UnlockWriteBuff(index);
- mcvread.notify_all();
- // yuvImg.create(cy*3/2, cx, CV_8UC1);
- // memcpy(yuvImg.data, frame->data[0], cy*cx);
- // memcpy(yuvImg.data + cy*cx,frame->data[1],cy*cx/4);
- // memcpy(yuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
- // cv::cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420);
- }
- }
- #define INBUF_SIZE 4096
- void ivh264framedecode::threaddecode()
- {
- const AVCodec *codec;
- AVCodecParserContext *parser;
- AVCodecContext *c= NULL;
- AVFrame *frame;
- uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
- int ret;
- AVPacket *pkt;
- av_register_all();
- pkt = av_packet_alloc();
- if (!pkt)
- exit(1);
- /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
- memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
- /* find the MPEG-1 video decoder */
- codec = avcodec_find_decoder(AV_CODEC_ID_H264);
- if (!codec) {
- fprintf(stderr, "Codec not found\n");
- exit(1);
- }
- parser = av_parser_init(codec->id);
- if (!parser) {
- fprintf(stderr, "parser not found\n");
- exit(1);
- }
- c = avcodec_alloc_context3(codec);
- if (!c) {
- fprintf(stderr, "Could not allocate video codec context\n");
- exit(1);
- }
- /* For some codecs, such as msmpeg4 and mpeg4, width and height
- MUST be initialized there because this information is not
- available in the bitstream. */
- /* open it */
- if (avcodec_open2(c, codec, NULL) < 0) {
- fprintf(stderr, "Could not open codec\n");
- exit(1);
- }
- frame = av_frame_alloc();
- if (!frame) {
- fprintf(stderr, "Could not allocate video frame\n");
- exit(1);
- }
- // char * strbuff = new char[10000000];
- // int ndatasize = 0;
- while (mbthreadrun) {
- iv::rawframedata xraw;
- if(mvectorrawframe.size()>0)
- {
- mmutexframe.lock();
- xraw = mvectorrawframe[0];
- mvectorrawframe.erase(mvectorrawframe.begin());
- mmutexframe.unlock();
- }
- else
- {
- std::unique_lock<std::mutex> lk(mmutex_cv);
- if(mcv.wait_for(lk, std::chrono::milliseconds(10)) == std::cv_status::timeout)
- {
- lk.unlock();
- continue;
- }
- lk.unlock();
- continue;
- }
- // read_h264_frame(strbuff,ndatasize);
- pkt->data = (uint8_t *)xraw.mpstr_ptr.get();
- pkt->size = xraw.ndatasize;
- if (pkt->size)
- {
- std::cout<<"decode ."<<std::endl;
- decode(c, frame, pkt);
- }
- }
- /* flush the decoder */
- // decode(c, frame, NULL, outfilename);
- av_parser_close(parser);
- avcodec_free_context(&c);
- av_frame_free(&frame);
- av_packet_free(&pkt);
- return;
- }
- void ivh264framedecode::addframedata(iv::rawframedata & xraw)
- {
- mmutexframe.lock();
- mvectorrawframe.push_back(xraw);
- mmutexframe.unlock();
- mcv.notify_all();
- }
|