#ifndef COMMONFFMPEGFUNC_HPP #define COMMONFFMPEGFUNC_HPP #include #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus } #endif class CommonFFmpeg { public: CommonFFmpeg():m_pInFmtCtx(nullptr),m_pInVideoStream(nullptr),m_pDict(nullptr){} ~CommonFFmpeg(){} public: void init() { av_register_all(); avformat_network_init(); } int rtspInputOpen(const char* rtsp) { av_dict_set(&m_pDict, "rtsp_transport", "tcp", 0); int ret = avformat_open_input(&m_pInFmtCtx, rtsp, NULL, &m_pDict); if (ret!=0) { fprintf(stderr, "could not open input file, ret: %d,info: %x\n",ret,AVERROR(ret)); return ret; } ret = avformat_find_stream_info(m_pInFmtCtx, NULL); if (ret<0) { fprintf(stderr, "could not find stream info\n"); return ret; } /* find first video stream */ for (unsigned i=0; inb_streams; i++) { if (m_pInFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { m_pInVideoStream = m_pInFmtCtx->streams[i]; break; } } if (m_pInVideoStream == NULL) { fprintf(stderr, "didn't find any video stream\n"); return -1; } return 0; } void rtspInputClose() { if(m_pInFmtCtx!=nullptr) avformat_close_input(&m_pInFmtCtx); if(m_pDict!=nullptr) av_dict_free(&m_pDict); } void* rtspCreatePkg() { //g_pkg.lock(); mutex().lock(); AVPacket* pkt = nullptr; try{pkt=new AVPacket();av_init_packet(pkt);} catch (...){if(pkt!=nullptr){delete pkt;pkt=nullptr;}} //g_pkg.unlock(); mutex().unlock(); return pkt; } void rtspDestroyPkg(void* packet) { mutex().lock(); if(packet!=nullptr) { AVPacket* pkg = static_cast(packet); av_free_packet(pkg); delete pkg; pkg = nullptr; } mutex().unlock(); } int rtspReadPkg(void* packet) { mutex().lock(); int ret = -1; if(packet!=nullptr) { AVPacket* pkg = static_cast(packet); ret = av_read_frame(m_pInFmtCtx, pkg); } mutex().unlock(); return ret; } void* getRtspStream() { return (void*)m_pInVideoStream; } int fileOutOpen(const char* filename,void* inStream) { AVStream* pInstream = (AVStream*)inStream; if(pInstream==nullptr) {DBG("instream is null");return -1;} int ret = avformat_alloc_output_context2(&m_pOutFmtCtx, NULL, NULL, filename); if(ret<0) { fprintf(stderr, "avformat_alloc_output_context2 failed, errorCode: %d\n",AVERROR(ret)); return -1; } /* * since all input files are supposed to be identical (framerate, dimension, color format, ...) * we can safely set output codec values from first input file */ m_pOutVideo_stream = avformat_new_stream(m_pOutFmtCtx, NULL); { AVCodecContext *c; c = m_pOutVideo_stream->codec; c->bit_rate = 400000; c->codec_id = pInstream->codec->codec_id; c->codec_type = pInstream->codec->codec_type; c->time_base.num = pInstream->time_base.num; c->time_base.den = pInstream->time_base.den; fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den); c->width = pInstream->codec->width; c->height = pInstream->codec->height; c->pix_fmt = pInstream->codec->pix_fmt; printf("%d %d %d", c->width, c->height, c->pix_fmt); c->flags = pInstream->codec->flags; c->flags |= CODEC_FLAG_GLOBAL_HEADER; c->me_range = pInstream->codec->me_range; c->max_qdiff = pInstream->codec->max_qdiff; c->qmin = pInstream->codec->qmin; c->qmax = pInstream->codec->qmax; c->qcompress = pInstream->codec->qcompress; } ret =avio_open(&m_pOutFmtCtx->pb, filename, AVIO_FLAG_WRITE); if(ret<0) { fprintf(stderr, "could not find stream info, errorCode: %d\n",AVERROR(ret)); return -1; } avformat_write_header(m_pOutFmtCtx, NULL); } void fileOutClose() { av_write_trailer(m_pOutFmtCtx); avio_close(m_pOutFmtCtx->pb); avcodec_close(m_pOutFmtCtx->streams[0]->codec); av_freep(&m_pOutFmtCtx->streams[0]->codec); av_freep(&m_pOutFmtCtx->streams[0]); av_free(m_pOutFmtCtx); m_pOutFmtCtx = nullptr; } int fileWritePkg(void* packet) { mutex().lock(); int ret = -1; if(packet!=nullptr) { AVPacket* pkg = static_cast(packet); //av_interleaved_write_frame(thisPtr->m_pOutFmtCtx, &i_pkt); ret = av_write_frame(m_pOutFmtCtx, pkg); } mutex().unlock(); return ret; } bool isKeyFrame(void* packet) { bool ret = false; if(packet!=nullptr) { AVPacket* pkg = static_cast(packet); if(pkg->flags&AV_PKT_FLAG_KEY) ret = true; } return ret; } long int getPkgDts(void* packet) { long int ret = 0; if(packet!=nullptr) { AVPacket* pkg = static_cast(packet); ret = pkg->dts; } return ret; } long int getPkgPts(void* packet) { long int ret = 0; if(packet!=nullptr) { AVPacket* pkg = static_cast(packet); ret = pkg->pts; } return ret; } void conversion(void* packet,const long int& firstKeyPts,const long int& firstKeyDts,void* inVideoStream) { mutex().lock(); if((packet!=nullptr)&&(inVideoStream!=nullptr)) { AVStream* inStream = (AVStream*)inVideoStream; AVPacket* pkg = static_cast(packet); pkg->pts -= firstKeyPts; pkg->dts -= firstKeyDts; pkg->pts = av_rescale_q_rnd(pkg->pts, inStream->time_base, m_pOutVideo_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkg->dts = av_rescale_q_rnd(pkg->dts, inStream->time_base, m_pOutVideo_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkg->duration = av_rescale_q(pkg->duration, inStream->time_base, m_pOutVideo_stream->time_base); pkg->pos = -1; } mutex().unlock(); } private: AVFormatContext * m_pInFmtCtx; AVStream *m_pInVideoStream; AVDictionary *m_pDict; AVFormatContext *m_pOutFmtCtx; AVStream *m_pOutVideo_stream; //static std::mutex g_pkg; inline static int& n() { static int tn = 0; return tn;} inline static std::mutex& mutex(){static std::mutex mtx;return mtx;} }; #endif //std::mutex CommonFFmpeg::g_pkg;