ivh264framedecode.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include "ivh264framedecode.h"
  2. ivh264framedecode::ivh264framedecode(int framewidth,int frameheight)
  3. {
  4. mframeheight = frameheight;
  5. mframewidth = framewidth;
  6. int i;
  7. for(i=0;i<FRAMEDECBUFSIZE;i++)
  8. {
  9. mdecbuf[i].mbuf.myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
  10. mdecbuf[i].mbuf.framewidth = mframewidth;
  11. mdecbuf[i].mbuf.frameheight = mframeheight;
  12. }
  13. mpthread = new std::thread(&ivh264framedecode::threaddecode,this);
  14. }
  15. int ivh264framedecode::GetUpdatedIndex()
  16. {
  17. if(mvectorupdateindex.size() == 0 )return -1;
  18. return mvectorupdateindex[0];
  19. }
  20. int ivh264framedecode::GetUpdatedIndex(int nwaitms)
  21. {
  22. std::unique_lock<std::mutex> lk(mmutex_cvread);
  23. if(mcvread.wait_for(lk, std::chrono::milliseconds(nwaitms)) == std::cv_status::timeout)
  24. {
  25. lk.unlock();
  26. return -1;
  27. }
  28. lk.unlock();
  29. if(mvectorupdateindex.size()>0)return mvectorupdateindex[0];
  30. return -1;
  31. }
  32. iv::framedecodebuf * ivh264framedecode::LockReadBuff(int nbufindex)
  33. {
  34. if(nbufindex < 0)return NULL;
  35. if(nbufindex >= FRAMEDECBUFSIZE)return NULL;
  36. mdecbuf[nbufindex].mMutex.lock();
  37. return &mdecbuf[nbufindex].mbuf;
  38. }
  39. void ivh264framedecode::UnlockReadBuff(int nbufindex)
  40. {
  41. mdecbuf[nbufindex].mMutex.unlock();
  42. mmutexstate.lock();
  43. mvectorupdateindex.erase(mvectorupdateindex.begin());
  44. mmutexstate.unlock();
  45. }
  46. int ivh264framedecode::GetEmptyIndex()
  47. {
  48. int i;
  49. int nindex = -1;
  50. mmutexstate.lock();
  51. for(i=0;i<FRAMEDECBUFSIZE;i++)
  52. {
  53. int j;
  54. bool bUsed = false;
  55. for(j=0;j<(int)(mvectorupdateindex.size());j++)
  56. {
  57. if(mvectorupdateindex[j] == i)
  58. {
  59. bUsed = true;
  60. break;
  61. }
  62. }
  63. if(bUsed == false)
  64. {
  65. nindex = i;
  66. break;
  67. }
  68. }
  69. mmutexstate.unlock();
  70. return nindex;
  71. }
  72. iv::framedecodebuf * ivh264framedecode::LockWriteBuff(int nbufindex)
  73. {
  74. if(nbufindex < 0)return NULL;
  75. if(nbufindex >= FRAMEDECBUFSIZE)return NULL;
  76. mdecbuf[nbufindex].mMutex.lock();
  77. return &mdecbuf[nbufindex].mbuf;
  78. }
  79. void ivh264framedecode::UnlockWriteBuff(int nbufindex)
  80. {
  81. mdecbuf[nbufindex].mMutex.unlock();
  82. mmutexstate.lock();
  83. mvectorupdateindex.push_back(nbufindex);
  84. mmutexstate.unlock();
  85. }
  86. void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)
  87. {
  88. // char buf[1024];
  89. int ret;
  90. ret = avcodec_send_packet(dec_ctx, pkt);
  91. if (ret < 0) {
  92. fprintf(stderr, "Error sending a packet for decoding\n");
  93. return;
  94. }
  95. while (ret >= 0) {
  96. ret = avcodec_receive_frame(dec_ctx, frame);
  97. if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  98. return;
  99. else if (ret < 0) {
  100. fprintf(stderr, "Error during decoding\n");
  101. return;
  102. }
  103. printf("saving frame %3d\n", dec_ctx->frame_number);
  104. fflush(stdout);
  105. /* the picture is allocated by the decoder. no need to
  106. free it */
  107. // snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
  108. // cv::Mat yuvImg;
  109. // cv::Mat rgbImg(cy, cx,CV_8UC3);
  110. int index = GetEmptyIndex();
  111. if(index < 0)
  112. {
  113. std::cout<<" no empty buffer used. "<<std::endl;
  114. break;
  115. }
  116. iv::framedecodebuf * pbuf = LockWriteBuff(index);
  117. if((mframeheight != frame->height)||(mframewidth != frame->width))
  118. {
  119. mframeheight = frame->height;
  120. mframewidth = frame->width;
  121. pbuf->myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
  122. pbuf->frameheight = mframeheight;
  123. pbuf->framewidth = mframewidth;
  124. std::cout<<"change width to : "<<mframewidth<<" change heigth to: "<<mframeheight<<std::endl;
  125. }
  126. int cy = mframeheight;
  127. int cx = mframewidth;
  128. memcpy(pbuf->myuvImg.data, frame->data[0], cy*cx);
  129. memcpy(pbuf->myuvImg.data + cy*cx,frame->data[1],cy*cx/4);
  130. memcpy(pbuf->myuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
  131. UnlockWriteBuff(index);
  132. mcvread.notify_all();
  133. // yuvImg.create(cy*3/2, cx, CV_8UC1);
  134. // memcpy(yuvImg.data, frame->data[0], cy*cx);
  135. // memcpy(yuvImg.data + cy*cx,frame->data[1],cy*cx/4);
  136. // memcpy(yuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
  137. // cv::cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420);
  138. }
  139. }
  140. #define INBUF_SIZE 4096
  141. void ivh264framedecode::threaddecode()
  142. {
  143. const AVCodec *codec;
  144. AVCodecParserContext *parser;
  145. AVCodecContext *c= NULL;
  146. AVFrame *frame;
  147. uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
  148. int ret;
  149. AVPacket *pkt;
  150. av_register_all();
  151. pkt = av_packet_alloc();
  152. if (!pkt)
  153. exit(1);
  154. /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
  155. memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
  156. /* find the MPEG-1 video decoder */
  157. codec = avcodec_find_decoder(AV_CODEC_ID_H264);
  158. if (!codec) {
  159. fprintf(stderr, "Codec not found\n");
  160. exit(1);
  161. }
  162. parser = av_parser_init(codec->id);
  163. if (!parser) {
  164. fprintf(stderr, "parser not found\n");
  165. exit(1);
  166. }
  167. c = avcodec_alloc_context3(codec);
  168. if (!c) {
  169. fprintf(stderr, "Could not allocate video codec context\n");
  170. exit(1);
  171. }
  172. /* For some codecs, such as msmpeg4 and mpeg4, width and height
  173. MUST be initialized there because this information is not
  174. available in the bitstream. */
  175. /* open it */
  176. if (avcodec_open2(c, codec, NULL) < 0) {
  177. fprintf(stderr, "Could not open codec\n");
  178. exit(1);
  179. }
  180. frame = av_frame_alloc();
  181. if (!frame) {
  182. fprintf(stderr, "Could not allocate video frame\n");
  183. exit(1);
  184. }
  185. // char * strbuff = new char[10000000];
  186. // int ndatasize = 0;
  187. while (mbthreadrun) {
  188. iv::rawframedata xraw;
  189. if(mvectorrawframe.size()>0)
  190. {
  191. mmutexframe.lock();
  192. xraw = mvectorrawframe[0];
  193. mvectorrawframe.erase(mvectorrawframe.begin());
  194. mmutexframe.unlock();
  195. }
  196. else
  197. {
  198. std::unique_lock<std::mutex> lk(mmutex_cv);
  199. if(mcv.wait_for(lk, std::chrono::milliseconds(10)) == std::cv_status::timeout)
  200. {
  201. lk.unlock();
  202. continue;
  203. }
  204. lk.unlock();
  205. continue;
  206. }
  207. // read_h264_frame(strbuff,ndatasize);
  208. pkt->data = (uint8_t *)xraw.mpstr_ptr.get();
  209. pkt->size = xraw.ndatasize;
  210. if (pkt->size)
  211. {
  212. std::cout<<"decode ."<<std::endl;
  213. decode(c, frame, pkt);
  214. }
  215. }
  216. /* flush the decoder */
  217. // decode(c, frame, NULL, outfilename);
  218. av_parser_close(parser);
  219. avcodec_free_context(&c);
  220. av_frame_free(&frame);
  221. av_packet_free(&pkt);
  222. return;
  223. }
  224. void ivh264framedecode::addframedata(iv::rawframedata & xraw)
  225. {
  226. mmutexframe.lock();
  227. mvectorrawframe.push_back(xraw);
  228. mmutexframe.unlock();
  229. mcv.notify_all();
  230. }