如何将FFmpeg的AVPacket传输到CUVID的CUVIDSOURCEDATAPACKET?或者如何使用FFmpeg的CUVID,任何演示?

时间:2017-03-16 09:30:13

标签: ffmpeg cuda

正如标题所说,我被困如何将FFmpeg的AVPacket转移到CUVID的CUVIDSOURCEDATAPACKET ,我的主要代码如下:`

AVPacket* avpkt;
avpkt = (AVPacket*)av_malloc(sizeof(AVPacket));
CUVIDSOURCEDATAPACKET cupkt;
int iPkt = 0;
while (av_read_frame(pFormatCtx, avpkt) >= 0) {
    if (avpkt->stream_index == videoindex) {

        cuCtxPushCurrent(g_oContext);

        if (avpkt && avpkt->size) {
            cupkt.payload_size = (unsigned long)avpkt->size;
            cupkt.payload = (const unsigned char*)avpkt->data;

            if (avpkt->pts != AV_NOPTS_VALUE) {
                cupkt.flags = CUVID_PKT_TIMESTAMP;
                if (pCodecCtx->pkt_timebase.num && pCodecCtx->pkt_timebase.den) {
                    AVRational tb;
                    tb.num = 1;
                    tb.den = AV_TIME_BASE;
                    cupkt.timestamp = av_rescale_q(avpkt->pts, pCodecCtx->pkt_timebase, tb);
                }
                else
                    cupkt.timestamp = avpkt->pts;
            }
        }
        else {
            cupkt.flags = CUVID_PKT_ENDOFSTREAM;
        }

        oResult = cuvidParseVideoData(hParser_, &cupkt);
        if ((cupkt.flags & CUVID_PKT_ENDOFSTREAM) || (oResult != CUDA_SUCCESS)) {
            break;
        }
        iPkt++;
        printf("Succeed to read avpkt %d !\n", iPkt);
        checkCudaErrors(cuCtxPopCurrent(NULL));
    }
    av_free_packet(avpkt);
}

如您所见,代码

cupkt.payload_size = (unsigned long)avpkt->size;
cupkt.payload = (const unsigned char*)avpkt->data;

需要纠正。 我英语很差,我希望我能清楚地表达自己。

1 个答案:

答案 0 :(得分:1)

今天我很高兴。在我问这个问题之后的一个晚上,我去看看FFmpeg的源代码,经过几个小时的努力,我发现我的代码和FFmpeg之间有一点区别。所以我会我自己回答这个问题。

AVBitStreamFilterContext* h264bsfc = NULL;
if (pCodecCtx->codec_id == AV_CODEC_ID_H264 || pCodecCtx->codec_id == AV_CODEC_ID_HEVC) {
    if (pCodecCtx->codec_id == AV_CODEC_ID_H264)
        h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
    else
        h264bsfc = av_bitstream_filter_init("hevc_mp4toannexb");
}

AVPacket *avpkt;
avpkt = (AVPacket *)av_malloc(sizeof(AVPacket));
CUVIDSOURCEDATAPACKET cupkt;
int iPkt = 0;
while (av_read_frame(pFormatCtx, avpkt) >= 0){
    if (avpkt->stream_index == videoindex){

        cuCtxPushCurrent(g_oContext);

        if (avpkt && avpkt->size) {
            if (h264bsfc)
            {
                av_bitstream_filter_filter(h264bsfc, pFormatCtx->streams[videoindex]->codec, NULL, &avpkt->data, &avpkt->size, avpkt->data, avpkt->size, 0);
            }

            cupkt.payload_size = (unsigned long)avpkt->size;
            cupkt.payload = (const unsigned char*)avpkt->data;

            if (avpkt->pts != AV_NOPTS_VALUE) {
                cupkt.flags = CUVID_PKT_TIMESTAMP;
                if (pCodecCtx->pkt_timebase.num && pCodecCtx->pkt_timebase.den){
                    AVRational tb;
                    tb.num = 1;
                    tb.den = AV_TIME_BASE;
                    cupkt.timestamp = av_rescale_q(avpkt->pts, pCodecCtx->pkt_timebase, tb);
                }
                else
                    cupkt.timestamp = avpkt->pts;
            }
        }
        else {
            cupkt.flags = CUVID_PKT_ENDOFSTREAM;
        }

        oResult = cuvidParseVideoData(hParser_, &cupkt);
        if ((cupkt.flags & CUVID_PKT_ENDOFSTREAM) || (oResult != CUDA_SUCCESS)){
            break;
        }
        iPkt++;
        //printf("Succeed to read avpkt %d !\n", iPkt);
        checkCudaErrors(cuCtxPopCurrent(NULL));
    }
    av_free_packet(avpkt);
}

if (h264bsfc)
{
    av_bitstream_filter_close(h264bsfc);
}

主要区别如下:

AVBitStreamFilterContext* h264bsfc = NULL;
if (pCodecCtx->codec_id == AV_CODEC_ID_H264 || pCodecCtx->codec_id == AV_CODEC_ID_HEVC) {
    if (pCodecCtx->codec_id == AV_CODEC_ID_H264)
        h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
    else
        h264bsfc = av_bitstream_filter_init("hevc_mp4toannexb");
}
········
if (h264bsfc)
{
    av_bitstream_filter_filter(h264bsfc, pFormatCtx->streams[videoindex]->codec, NULL, &avpkt->data, &avpkt->size, avpkt->data, avpkt->size, 0);
}
·········
if (h264bsfc)
{
    av_bitstream_filter_close(h264bsfc);
}

这是因为我使用的文件是H264格式,必须用H264的NALU做一些事情(我不知道它是什么,我从其他人的问题得到它,我不知道很明显,也许问题不像我说的那样。。我添加的代码对我有用,我希望我的帮助可以帮助你。我记得,如果你对我说的话感到困惑,我的英语很差,只需转到代码。