|
@@ -1,6 +1,8 @@
|
|
#include "ivh264framedecode.h"
|
|
#include "ivh264framedecode.h"
|
|
|
|
|
|
|
|
+#include <iostream>
|
|
|
|
|
|
|
|
+#ifdef USE_QSV
|
|
static void yuvNV12ToI420(char *NV12,int w,int h,char *I420)
|
|
static void yuvNV12ToI420(char *NV12,int w,int h,char *I420)
|
|
{
|
|
{
|
|
memcpy(I420,NV12,w*h);//y分量
|
|
memcpy(I420,NV12,w*h);//y分量
|
|
@@ -10,17 +12,23 @@ static void yuvNV12ToI420(char *NV12,int w,int h,char *I420)
|
|
memcpy(I420+w*h+w*h/4+i,NV12+w*h+j+1,1);//v分量
|
|
memcpy(I420+w*h+w*h/4+i,NV12+w*h+j+1,1);//v分量
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
-
|
|
|
|
-ivh264framedecode::ivh264framedecode(int framewidth,int frameheight)
|
|
|
|
|
|
+ivh264framedecode::ivh264framedecode(int framewidth,int frameheight,bool bJpegEnc)
|
|
{
|
|
{
|
|
|
|
+ mbTransJpeg = bJpegEnc;
|
|
mframeheight = frameheight;
|
|
mframeheight = frameheight;
|
|
mframewidth = framewidth;
|
|
mframewidth = framewidth;
|
|
|
|
+ mjpegdata.mbupdate = false;
|
|
|
|
|
|
int i;
|
|
int i;
|
|
for(i=0;i<FRAMEDECBUFSIZE;i++)
|
|
for(i=0;i<FRAMEDECBUFSIZE;i++)
|
|
{
|
|
{
|
|
|
|
+#ifndef USEJPEG_NOOPENCV
|
|
mdecbuf[i].mbuf.myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
|
|
mdecbuf[i].mbuf.myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
|
|
|
|
+#else
|
|
|
|
+ mdecbuf[i].mbuf.mpyuv_ptr = std::shared_ptr<char>(new char[mframeheight* mframewidth*3/2]);
|
|
|
|
+#endif
|
|
mdecbuf[i].mbuf.framewidth = mframewidth;
|
|
mdecbuf[i].mbuf.framewidth = mframewidth;
|
|
mdecbuf[i].mbuf.frameheight = mframeheight;
|
|
mdecbuf[i].mbuf.frameheight = mframeheight;
|
|
|
|
|
|
@@ -109,6 +117,118 @@ void ivh264framedecode::UnlockWriteBuff(int nbufindex)
|
|
mmutexstate.unlock();
|
|
mmutexstate.unlock();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+int ivh264framedecode::GetJpegData(std::shared_ptr<char> & pstr_ptr,int & ndatasize,int nwaitms)
|
|
|
|
+{
|
|
|
|
+ if(mjpegdata.mbupdate)
|
|
|
|
+ {
|
|
|
|
+ mjpegdata.mmutexdata.lock();
|
|
|
|
+ pstr_ptr = mjpegdata.mpstr_ptr;
|
|
|
|
+ ndatasize = mjpegdata.ndatasize;
|
|
|
|
+ mjpegdata.mbupdate = false;
|
|
|
|
+ mjpegdata.mmutexdata.unlock();
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(nwaitms<=0)return 0;
|
|
|
|
+
|
|
|
|
+ std::unique_lock<std::mutex> lk(mmutex_cvjpeg);
|
|
|
|
+ if(mcvjpeg.wait_for(lk, std::chrono::milliseconds(nwaitms)) == std::cv_status::timeout)
|
|
|
|
+ {
|
|
|
|
+ lk.unlock();
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ lk.unlock();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(mjpegdata.mbupdate)
|
|
|
|
+ {
|
|
|
|
+ mjpegdata.mmutexdata.lock();
|
|
|
|
+ pstr_ptr = mjpegdata.mpstr_ptr;
|
|
|
|
+ ndatasize = mjpegdata.ndatasize;
|
|
|
|
+ mjpegdata.mmutexdata.unlock();
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ivh264framedecode::encodejpeg(AVFrame *frame)
|
|
|
|
+{
|
|
|
|
+ static int nindex = 0;
|
|
|
|
+ int nsample = 3;
|
|
|
|
+
|
|
|
|
+ if(nindex>nsample)
|
|
|
|
+ {
|
|
|
|
+ nindex = 0;
|
|
|
|
+ }
|
|
|
|
+ nindex++;
|
|
|
|
+ if(nindex != 1)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ av_opt_set(mpCodecCtxJpeg->priv_data, "qscale:v", "95", 0);
|
|
|
|
+#define DEBUG_ENCODEJPEG
|
|
|
|
+ int ret;
|
|
|
|
+ AVCodecContext * enc_ctx = mpCodecCtxJpeg;
|
|
|
|
+ AVPacket pkt;
|
|
|
|
+ int y_size = enc_ctx->width * enc_ctx->height;
|
|
|
|
+
|
|
|
|
+#ifdef DEBUG_ENCODEJPEG
|
|
|
|
+ int64_t time1 = std::chrono::system_clock::now().time_since_epoch().count()/1000;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ av_new_packet(&pkt, y_size*2); //给AVPacket申请空间
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ret = avcodec_send_frame(enc_ctx, frame);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ fprintf(stderr, "Error sending a frame for jpeg encoding\n");
|
|
|
|
+ av_packet_unref(&pkt);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ while (ret >= 0) {
|
|
|
|
+ ret = avcodec_receive_packet(enc_ctx, &pkt);
|
|
|
|
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
|
|
|
+ {
|
|
|
|
+ av_packet_unref(&pkt);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ else if (ret < 0) {
|
|
|
|
+ fprintf(stderr, "Error during encoding\n");
|
|
|
|
+ av_packet_unref(&pkt);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ std::shared_ptr<char> pstr_data = std::shared_ptr<char>(new char[pkt.size]);
|
|
|
|
+ memcpy(pstr_data.get(),pkt.data,pkt.size);
|
|
|
|
+ mjpegdata.mmutexdata.lock();
|
|
|
|
+ mjpegdata.mpstr_ptr = pstr_data;
|
|
|
|
+ mjpegdata.ndatasize = pkt.size;
|
|
|
|
+ mjpegdata.mnupdatetime = std::chrono::system_clock::now().time_since_epoch().count();
|
|
|
|
+ mjpegdata.mbupdate = true;
|
|
|
|
+ mjpegdata.mmutexdata.unlock();
|
|
|
|
+ mcvjpeg.notify_all();
|
|
|
|
+
|
|
|
|
+#ifdef DEBUG_ENCODEJPEG
|
|
|
|
+ int64_t time2 = std::chrono::system_clock::now().time_since_epoch().count()/1000;
|
|
|
|
+ double codetime = time2-time1;
|
|
|
|
+ codetime = codetime/1000.0;
|
|
|
|
+ std::cout<<" pictrue size: "<<pkt.size<<" code time: "<<codetime<< std::endl;
|
|
|
|
+#endif
|
|
|
|
+// fwrite(pkt->data, 1, pkt->size, outfile);
|
|
|
|
+ av_packet_unref(&pkt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)
|
|
void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)
|
|
{
|
|
{
|
|
// char buf[1024];
|
|
// char buf[1024];
|
|
@@ -138,13 +258,20 @@ void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket
|
|
// snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
|
|
// snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
|
|
|
|
|
|
|
|
|
|
|
|
+ if(mbTransJpeg)
|
|
|
|
+ {
|
|
|
|
+ // encodejpeg(frame);
|
|
|
|
+ }
|
|
// cv::Mat yuvImg;
|
|
// cv::Mat yuvImg;
|
|
// cv::Mat rgbImg(cy, cx,CV_8UC3);
|
|
// cv::Mat rgbImg(cy, cx,CV_8UC3);
|
|
|
|
|
|
int index = GetEmptyIndex();
|
|
int index = GetEmptyIndex();
|
|
if(index < 0)
|
|
if(index < 0)
|
|
{
|
|
{
|
|
- std::cout<<" no empty buffer used. "<<std::endl;
|
|
|
|
|
|
+#ifndef USEJPEG_NOOPENCV
|
|
|
|
+// std::cout<<" no empty buffer used. "<<std::endl;
|
|
|
|
+#endif
|
|
|
|
+ // index = 0;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
iv::framedecodebuf * pbuf = LockWriteBuff(index);
|
|
iv::framedecodebuf * pbuf = LockWriteBuff(index);
|
|
@@ -153,7 +280,11 @@ void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket
|
|
{
|
|
{
|
|
mframeheight = frame->height;
|
|
mframeheight = frame->height;
|
|
mframewidth = frame->width;
|
|
mframewidth = frame->width;
|
|
|
|
+#ifndef USEJPEG_NOOPENCV
|
|
pbuf->myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
|
|
pbuf->myuvImg.create(mframeheight*3/2, mframewidth, CV_8UC1);
|
|
|
|
+#else
|
|
|
|
+ pbuf->mpyuv_ptr = std::shared_ptr<char>(new char[mframeheight*mframewidth*3/2]);
|
|
|
|
+#endif
|
|
pbuf->frameheight = mframeheight;
|
|
pbuf->frameheight = mframeheight;
|
|
pbuf->framewidth = mframewidth;
|
|
pbuf->framewidth = mframewidth;
|
|
std::cout<<"change width to : "<<mframewidth<<" change heigth to: "<<mframeheight<<std::endl;
|
|
std::cout<<"change width to : "<<mframewidth<<" change heigth to: "<<mframeheight<<std::endl;
|
|
@@ -172,13 +303,47 @@ void ivh264framedecode::decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifndef USE_QSV
|
|
#ifndef USE_QSV
|
|
|
|
+#ifndef USEJPEG_NOOPENCV
|
|
memcpy(pbuf->myuvImg.data, frame->data[0], cy*cx);
|
|
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,frame->data[1],cy*cx/4);
|
|
memcpy(pbuf->myuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
|
|
memcpy(pbuf->myuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
|
|
|
|
+#else
|
|
|
|
+ char * pstrdata = pbuf->mpyuv_ptr.get();
|
|
|
|
+ memcpy(pstrdata,frame->data[0],cy*cx);
|
|
|
|
+ memcpy(pstrdata +cy*cx,frame->data[1],cy*cx/4);
|
|
|
|
+ memcpy(pstrdata +cy*cx+cy*cx/4,frame->data[2],cy*cx/4);
|
|
#endif
|
|
#endif
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ if(mbTransJpeg)
|
|
|
|
+ {
|
|
|
|
+ std::vector<int> param = std::vector<int>(2);
|
|
|
|
+ param[0] = CV_IMWRITE_JPEG_QUALITY;
|
|
|
|
+ param[1] = 95; // default(95) 0-100
|
|
|
|
+ std::vector<unsigned char> buff;
|
|
|
|
+
|
|
|
|
+ cv::Mat mat1;
|
|
|
|
+
|
|
|
|
+ cv::cvtColor(pbuf->myuvImg,mat1,cv::COLOR_YUV2BGR_I420);
|
|
|
|
+ cv::imencode(".jpg", mat1, buff, param);
|
|
|
|
+
|
|
|
|
+ std::shared_ptr<char> pstr_data = std::shared_ptr<char>(new char[buff.size()]);
|
|
|
|
+ memcpy(pstr_data.get(),buff.data(),buff.size());
|
|
|
|
+ mjpegdata.mmutexdata.lock();
|
|
|
|
+ mjpegdata.mpstr_ptr = pstr_data;
|
|
|
|
+ mjpegdata.ndatasize =buff.size();
|
|
|
|
+ mjpegdata.mnupdatetime = std::chrono::system_clock::now().time_since_epoch().count();
|
|
|
|
+ mjpegdata.mbupdate = true;
|
|
|
|
+ mjpegdata.mmutexdata.unlock();
|
|
|
|
+ mcvjpeg.notify_all();
|
|
|
|
+
|
|
|
|
+ buff.clear();
|
|
|
|
+ }
|
|
UnlockWriteBuff(index);
|
|
UnlockWriteBuff(index);
|
|
mcvread.notify_all();
|
|
mcvread.notify_all();
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
// yuvImg.create(cy*3/2, cx, CV_8UC1);
|
|
// yuvImg.create(cy*3/2, cx, CV_8UC1);
|
|
// memcpy(yuvImg.data, frame->data[0], cy*cx);
|
|
// memcpy(yuvImg.data, frame->data[0], cy*cx);
|
|
// memcpy(yuvImg.data + cy*cx,frame->data[1],cy*cx/4);
|
|
// memcpy(yuvImg.data + cy*cx,frame->data[1],cy*cx/4);
|
|
@@ -198,7 +363,7 @@ void ivh264framedecode::threaddecode()
|
|
AVCodecContext *c= NULL;
|
|
AVCodecContext *c= NULL;
|
|
AVFrame *frame;
|
|
AVFrame *frame;
|
|
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
|
|
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
|
|
- int ret;
|
|
|
|
|
|
+// int ret;
|
|
AVPacket *pkt;
|
|
AVPacket *pkt;
|
|
|
|
|
|
#ifndef USE_QSV
|
|
#ifndef USE_QSV
|
|
@@ -261,6 +426,50 @@ void ivh264framedecode::threaddecode()
|
|
exit(1);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+// AVFormatContext* pFormatCtx;
|
|
|
|
+// AVStream* pStream;
|
|
|
|
+ AVCodec* pCodec;
|
|
|
|
+ if(mbTransJpeg)
|
|
|
|
+ {
|
|
|
|
+ // pFormatCtx = avformat_alloc_context(); //分配AVFormatCtx
|
|
|
|
+// pStream = avformat_new_stream(pFormatCtx, 0);
|
|
|
|
+// if (NULL == pStream)
|
|
|
|
+// {
|
|
|
|
+// std::cout<<" JPEG Create pStream fail."<<std::endl;
|
|
|
|
+// return;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ pCodec = avcodec_find_encoder(AV_CODEC_ID_MJPEG); //查找编码器
|
|
|
|
+ if (NULL == pCodec)
|
|
|
|
+ {
|
|
|
|
+ printf("can not find jpeg codec!\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*设置相关信息*/
|
|
|
|
+ mpCodecCtxJpeg = avcodec_alloc_context3(pCodec);
|
|
|
|
+// mpCodecCtxJpeg = pStream->codec;
|
|
|
|
+ mpCodecCtxJpeg->codec_id = AV_CODEC_ID_MJPEG;
|
|
|
|
+ mpCodecCtxJpeg->codec_type = AVMEDIA_TYPE_VIDEO;
|
|
|
|
+ mpCodecCtxJpeg->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
|
|
|
+ mpCodecCtxJpeg->width = mframewidth;
|
|
|
|
+ mpCodecCtxJpeg->height = mframeheight;
|
|
|
|
+ mpCodecCtxJpeg->time_base.num = 1;
|
|
|
|
+ mpCodecCtxJpeg->time_base.den = 25;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ av_opt_set_int(mpCodecCtxJpeg->priv_data, "qscale",1, 0);
|
|
|
|
+
|
|
|
|
+ if (avcodec_open2(mpCodecCtxJpeg, pCodec, NULL) < 0)
|
|
|
|
+ {
|
|
|
|
+ printf("con not open jpeg codec!\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
// char * strbuff = new char[10000000];
|
|
// char * strbuff = new char[10000000];
|
|
// int ndatasize = 0;
|
|
// int ndatasize = 0;
|
|
while (mbthreadrun) {
|
|
while (mbthreadrun) {
|
|
@@ -292,6 +501,8 @@ void ivh264framedecode::threaddecode()
|
|
{
|
|
{
|
|
// std::cout<<"decode ."<<std::endl;
|
|
// std::cout<<"decode ."<<std::endl;
|
|
decode(c, frame, pkt);
|
|
decode(c, frame, pkt);
|
|
|
|
+
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -300,6 +511,9 @@ void ivh264framedecode::threaddecode()
|
|
// decode(c, frame, NULL, outfilename);
|
|
// decode(c, frame, NULL, outfilename);
|
|
|
|
|
|
|
|
|
|
|
|
+ avcodec_free_context(&mpCodecCtxJpeg);
|
|
|
|
+// avcodec_close(pStream->codec);
|
|
|
|
+// avformat_free_context(pFormatCtx);
|
|
|
|
|
|
av_parser_close(parser);
|
|
av_parser_close(parser);
|
|
avcodec_free_context(&c);
|
|
avcodec_free_context(&c);
|
|
@@ -311,6 +525,7 @@ void ivh264framedecode::threaddecode()
|
|
|
|
|
|
void ivh264framedecode::addframedata(iv::rawframedata & xraw)
|
|
void ivh264framedecode::addframedata(iv::rawframedata & xraw)
|
|
{
|
|
{
|
|
|
|
+ if(mvectorrawframe.size()>10000)return;
|
|
mmutexframe.lock();
|
|
mmutexframe.lock();
|
|
mvectorrawframe.push_back(xraw);
|
|
mvectorrawframe.push_back(xraw);
|
|
mmutexframe.unlock();
|
|
mmutexframe.unlock();
|