c++ OUTDATED -关键帧之间的FFMPEG解码瑕疵

mgdq6dx1  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(190)
    • 将问题标记为过时,因为使用了过时的**avcodec_decode_video2

我目前在使用ffmpegs api解码视频时遇到了伪像。在我假设为中间帧的帧上,伪像只会从帧中的活动移动缓慢地构建。这些伪像会构建50 - 100帧,直到我假设一个关键帧重置它们。然后帧被正确解码,伪像继续构建。
有一件事困扰着我,我有几个视频样本是30fps(H264)的工作正常,但我所有的60fps视频(H264)经验的问题。
我目前没有足够的声誉来发布图像,所以希望这个链接将工作. http://i.imgur.com/PPXXkJc.jpg

int numBytes;
int frameFinished;
AVFrame* decodedRawFrame;
AVFrame* rgbFrame;

    //Enum class for decoding results, used to break decode loop when a frame is gathered
DecodeResult retResult = DecodeResult::Fail;

decodedRawFrame = av_frame_alloc();
rgbFrame = av_frame_alloc();
if (!decodedRawFrame) {
    fprintf(stderr, "Could not allocate video frame\n");
    return DecodeResult::Fail;
}

numBytes = avpicture_get_size(PIX_FMT_RGBA, mCodecCtx->width,mCodecCtx->height);
uint8_t* buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

avpicture_fill((AVPicture *) rgbFrame, buffer, PIX_FMT_RGBA, mCodecCtx->width, mCodecCtx->height);

AVPacket packet;

while(av_read_frame(mFormatCtx, &packet) >= 0 && retResult != DecodeResult::Success)
{
    // Is this a packet from the video stream?
    if (packet.stream_index == mVideoStreamIndex)
    {
        // Decode video frame
        int decodeValue = avcodec_decode_video2(mCodecCtx, decodedRawFrame, &frameFinished, &packet);

        // Did we get a video frame?
        if (frameFinished)// && rgbFrame->pict_type != AV_PICTURE_TYPE_NONE )
        {
            // Convert the image from its native format to RGB
            int SwsFlags = SWS_BILINEAR;
            // Accurate round clears up a problem where the start
                            // of videos have green bars on them
            SwsFlags |= SWS_ACCURATE_RND;
            struct SwsContext *ctx = sws_getCachedContext(NULL, mCodecCtx->width, mCodecCtx->height, mCodecCtx->pix_fmt, mCodecCtx->width, mCodecCtx->height, 
                PIX_FMT_RGBA, SwsFlags, NULL, NULL, NULL);
            sws_scale(ctx, decodedRawFrame->data, decodedRawFrame->linesize, 0, mCodecCtx->height, rgbFrame->data, rgbFrame->linesize);
            
            //if(count%5 == 0 && count < 105)
            //  DebugSavePPMImage(rgbFrame, mCodecCtx->width, mCodecCtx->height, count);
            
            ++count;
            // Viewable frame is a struct to hold buffer and frame together in a queue
            ViewableFrame frame;
            frame.buffer = buffer;
            frame.frame = rgbFrame;
            mFrameQueue.push(frame);
            
            
            retResult = DecodeResult::Success;
                        
            sws_freeContext(ctx);
        }
    }
    
    // Free the packet that was allocated by av_read_frame
    av_free_packet(&packet);
}

// Check for end of file leftover frames
if(retResult != DecodeResult::Success)
{
    int result = av_read_frame(mFormatCtx, &packet);
    if(result < 0)
        isEoF = true;
    av_free_packet(&packet); 
}   

// Free the YUV frame
av_frame_free(&decodedRawFrame);

我尝试建立一个解码帧队列,然后使用并根据需要释放。我的帧分离是否会导致中间帧解码不正确?我还打破了解码循环,一旦我成功地收集了一个帧(解码::成功,我见过的大多数例子往往循环通过整个视频。
所有编解码器内容、视频流信息和格式上下文的设置完全如https://github.com/chelyaev/ffmpeg-tutorial/blob/master/tutorial01.c的main函数所示
如有任何建议,我们将不胜感激。

vsnjm48y

vsnjm48y1#

如果有人发现自己处于类似的位置,请参考。显然,对于一些较旧版本的FFMPEG,使用sws_scale转换图像时会出现问题,并且不会更改最终帧的实际尺寸。如果您使用以下命令为SwsContext创建一个标志:
内部软件标志=软件_双线性;//任何您想要的SwsFlags|= SWS_准确度_RND;// Under the hood强制ffmpeg使用与缩放时相同的逻辑
SWS_ACCURATE_RND有一个性能损失,但对于普通视频来说,它可能不是那么明显。这将删除绿色的飞溅,或沿着纹理边缘的绿色条(如果存在)。
我想感谢多媒体迈克和乔治Y,他们也是正确的,因为我解码帧的方式没有正确地保存数据包,这就是导致视频伪影从以前的帧建设。

相关问题