派生自 development/c++

xuxiuxi
2019-03-15 cdfb8eb2a956d25d688033be735f4741b2ab58bd
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp
@@ -144,39 +144,50 @@
void BASICGB28181::FFmpegDecoderJPG::BareFlowDecoderThd(FFmpegDecoderJPG *p_this) {
    DBG(p_this->m_camIdx << "  BareFlowDecoderThd ok ... gpuIdx is " << p_this->m_gpuIdx);
    p_this->m_running = true;
    av_register_all();
    avformat_network_init();
    AVFormatContext *ic = avformat_alloc_context();
//    av_register_all();
//    avformat_network_init();
    p_this->ic = avformat_alloc_context();
    unsigned char *iobuffer = (unsigned char *) av_malloc(p_this->m_buf_size);
    AVIOContext *avio = avio_alloc_context(iobuffer, p_this->m_buf_size, 0, p_this, p_this->read_data, NULL, NULL);
    ic->pb = avio;
    p_this->iobuffer = (unsigned char *) av_malloc(p_this->m_buf_size);
    p_this->avio = avio_alloc_context(p_this->iobuffer, p_this->m_buf_size, 0, p_this, p_this->read_data, NULL, NULL);
    p_this->ic->pb = p_this->avio;
    int err = av_probe_input_buffer(ic->pb, &ic->iformat, nullptr, nullptr, 0, p_this->m_buf_size);
    int err1 = avformat_open_input(&ic, "", NULL, NULL);
    int err2 = avformat_find_stream_info(ic, nullptr);
    int err = av_probe_input_buffer(p_this->ic->pb, &p_this->ic->iformat, nullptr, nullptr, 0, p_this->m_buf_size);
    if(err){
        ERR("av_probe_input_buffer" << err);
    }
    err = avformat_open_input(&p_this->ic, "", NULL, NULL);
    if(err){
        ERR("avformat_open_input" << err);
    }
//    int err2 = avformat_find_stream_info(ic, nullptr);
    err = avformat_find_stream_info(p_this->ic, NULL);
    if(err){
        ERR("avformat_find_stream_info" << err);
    }
    int vi = -1;
    for (int i = 0; i < ic->nb_streams; ++i) {
        if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    for (int i = 0; i < p_this->ic->nb_streams; ++i) {
        if (p_this->ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            vi = i;
            break;
        }
    }
    AVStream *stream = ic->streams[vi];
    p_this->video_st = stream;
    AVCodecContext *ctx = avcodec_alloc_context3(nullptr);
    int err3 = avcodec_parameters_to_context(ctx, stream->codecpar);
    p_this->stream = p_this->ic->streams[vi];
    p_this->video_st = p_this->stream;
    p_this->ctx = avcodec_alloc_context3(nullptr);
    int err3 = avcodec_parameters_to_context(p_this->ctx, p_this->stream->codecpar);
    AVCodec *codec = avcodec_find_decoder(ctx->codec_id);
    p_this->codec = avcodec_find_decoder(p_this->ctx->codec_id);
    //是否启用GPU
    if (p_this->m_gpuIdx >= 0) {
        if (codec != NULL) {
        if (p_this->codec != NULL) {
            char cuvidName[40] = {0};
            sprintf(cuvidName, "%s_cuvid", codec->name);
            if (!strcmp(codec->name, "h264") || !strcmp(codec->name, "h265") || !strcmp(codec->name, "hevc")) {
                AVCodec *codec_cuvid = avcodec_find_decoder_by_name(cuvidName);
                if (codec_cuvid != NULL) {
                    codec = codec_cuvid;
            sprintf(cuvidName, "%s_cuvid", p_this->codec->name);
            if (!strcmp(p_this->codec->name, "h264") || !strcmp(p_this->codec->name, "h265") ||
                !strcmp(p_this->codec->name, "hevc")) {
                p_this->codec_cuvid = avcodec_find_decoder_by_name(cuvidName);
                if (p_this->codec_cuvid != NULL) {
                    p_this->codec = p_this->codec_cuvid;
                } else {
//                    return false;
                    ERR("codec_cuvid is NULL");
@@ -184,12 +195,11 @@
            }
        }
    }
    int err4 = avcodec_open2(ctx, codec, nullptr);
    int err4 = avcodec_open2(p_this->ctx, p_this->codec, nullptr);
    AVPacket pkt;
    av_init_packet(&pkt);
    av_init_packet(&p_this->pkt);
    AVFrame *frame = av_frame_alloc();
    p_this->frame = av_frame_alloc();
    unsigned int usleepTime = (1000 / p_this->m_fps) - 12;
    usleepTime *= 1000;
    DBG(" before while <<usleepTime is " << usleepTime);
@@ -197,13 +207,16 @@
#ifdef TestCode
        ClockTimer Test("while time");
#endif
        int err5 = av_read_frame(ic, &pkt);
        av_packet_unref(&p_this->pkt);
        p_this->pkt.data = NULL;
        p_this->pkt.size = 0;
        int err5 = av_read_frame(p_this->ic, &p_this->pkt);
        //# todo save package
        p_this->frame_number++;
        int err6 = avcodec_send_packet(ctx, &pkt);
//        av_packet_unref(&pkt);
        int err7 = avcodec_receive_frame(ctx, frame);
        int err6 = avcodec_send_packet(p_this->ctx, &p_this->pkt);
        int err7 = avcodec_receive_frame(p_this->ctx, p_this->frame);
        if ((err7 == AVERROR(EAGAIN)) || (err5 < 0) || (err6 < 0)) {
            ERR(" error << err7:" << err7 << "  err5: " << err5 << " err6: " << err6);
            usleep(40000);
@@ -211,11 +224,11 @@
        }
        //DBG("GotPicture "<<m_camId<<":"<<frame_number);
        //放在此处是因为之前放在前面,收到的帧不完成
        p_this->SaveToPacketVector(pkt);
        p_this->SaveToPacketVector(p_this->pkt);
        p_this->CheckSave();
//        BASICGB28181::avframe_to_cvmat(frame).copyTo(p_this->m_image);
        p_this->m_image = std::move(BASICGB28181::avframe_to_cvmat(frame));
        p_this->m_image = std::move(BASICGB28181::avframe_to_cvmat(p_this->frame));
#ifdef TestCode
        {
@@ -271,7 +284,7 @@
    }
    DBG(" after while ");
    av_frame_free(&frame);
    av_frame_free(&p_this->frame);
}
bool BASICGB28181::FFmpegDecoderJPG::startThd(const std::string &camIdx, const int &fps, const int &gpuIdx) {
@@ -375,7 +388,7 @@
            delete iter->m_packet.data;
            iter = m_packetsVec.erase(iter);
            while (!(iter->m_packet.flags & AV_PKT_FLAG_KEY)) {
//                INFO("DropFrame: " << iter->m_frameId);
                INFO("DropFrame: " << iter->m_frameId);
                delete iter->m_packet.data;
                iter = m_packetsVec.erase(iter);
            }
@@ -386,15 +399,17 @@
bool BASICGB28181::FFmpegDecoderJPG::SaveVideo(std::string path, int64_t lastFrameId) {
    std::lock_guard<std::mutex> lock(g_mutex);
    INFO("SaveVideo: " << path);
    INFO("SaveVideo: " << path << "m_packetsVec.size : " <<m_packetsVec.size());
    if (!m_packetsVec.empty()) {
        startWrite(path.c_str());
        int64_t firstKeyFramePts = m_packetsVec[0].m_packet.pts;
        int64_t firstKeyFrameDts = m_packetsVec[0].m_packet.dts;
        unsigned long int frame_index = 0;
        for (const auto &item:m_packetsVec) {
            if (item.m_frameId < lastFrameId) {
                DBG("item.m_frameId < lastFrameId   " << item.m_frameId << "  " << lastFrameId);
                conversion(const_cast<AVPacket *> (&item.m_packet), firstKeyFramePts, firstKeyFrameDts, video_st);
                conversion(const_cast<AVPacket *> (&item.m_packet), firstKeyFramePts, firstKeyFrameDts, video_st, frame_index);
                frame_index++;
                av_write_frame(m_pOutFmtCtx, &item.m_packet);
            } else {
                DBG("item.m_frameId > lastFrameId   " << item.m_frameId << "  " << lastFrameId);
@@ -517,11 +532,12 @@
int BASICGB28181::FFmpegDecoderJPG::stopWrite() {
    if (m_pOutFmtCtx == nullptr) return -1;
    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]);
    avio_close(m_pOutFmtCtx->pb);
    av_free(m_pOutFmtCtx);
    m_pOutFmtCtx = nullptr;
    m_bstartWrite = false;
@@ -530,23 +546,44 @@
void BASICGB28181::FFmpegDecoderJPG::conversion(void *packet, const long int &firstKeyPts, const long int &firstKeyDts,
                                                void *inVideoStream) {
                                                void *inVideoStream, unsigned long int frame_index) {
    if ((packet != nullptr) && (inVideoStream != nullptr)) {
        AVStream *inStream = (AVStream *) inVideoStream;
        AVPacket *pkg = static_cast<AVPacket *>(packet);
//            static int a = 0;
//            pkg->dts = a++;
//            pkg->pts = a;
        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;
//        static unsigned  long int frame_index = 0
//            pkg->dts = ++frame_index;
//            pkg->pts = frame_index;
            //todo
//        if(pkg->pts==AV_NOPTS_VALUE){
            DBG("frame_index==%d\n" << frame_index);
            //Write PTS
            AVRational time_base1=inStream->time_base;
            //Duration between 2 frames (us)
            int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(inStream->r_frame_rate);
            //Parameters
            pkg->pts=(double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE);
            pkg->dts=pkg->pts;
            pkg->duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);
//            frame_index++;
//        }
//        else{
//            DBG("pts" << pkg->pts << "firstKeyPts" << firstKeyPts);
//            DBG("dts" << pkg->dts << "firstKeyDts" << firstKeyDts);
//            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;
//        }
        DBG("pts:" << pkg->pts);
        DBG("dts:" << pkg->dts);
    }
}