【问题标题】:Seeking with FFmpeg gives old frames with new packet timestamp使用 FFmpeg 搜索会为旧帧提供新的数据包时间戳
【发布时间】:2017-08-17 15:56:22
【问题描述】:

我正在使用 FFmpeg 2.7 编写一个示例应用程序,该应用程序将执行以下操作:

  1. 从给定的 .mov 文件中读取视频数据包
  2. 在解码视频 10 秒后寻找指定位置,然后再继续 10 秒
  3. 在搜索之前和之后解码所有视频数据包并将它们写入目标文件。

在此过程中,我还将接收到的所有视频帧转储到原始图像文件中,使用原始数据包的 PTS 作为文件名。我注意到,即使在搜索发生之后(由时间戳中的跳转注意到),搜索后的前几帧包含新的时间戳,但旧帧(即我会在没有搜索的情况下收到的帧)。

These images illustrate the problem.

以下是我正在使用的代码的 sn-p:

int SeekAndTranscode::_TranscodePacket(AVPacket &packet, AVFrame *frame)
{
    if(packet.stream_index == _videoStreamIndex)
    {
        int status = avcodec_decode_video2(&_videoDecContext, frame, &gotFrame, &packet);
        if (status < 0)
        {
            fprintf(stderr, "\nError decoding video frame\n");
            exit(1);
        }

        if (gotFrame)
        {
            if (frame->width != _width || frame->height != _height ||
                frame->format != _pixelFormat)
            {
                return -1;
            }

            vector<uint8_t> rgbData;
            rgbData.resize(_width * _height * 4);

            uint8_t *rgbSrc[3]= {&rgbData[0], NULL, NULL};
            int rgbStride[3]={4 * _width, 0, 0};

            sws_scale(_csc, frame->data, frame->linesize, 0, _height, rgbSrc, rgbStride);

            int64_t pts = packet.pts * AV_TIME_BASE / _videoDecContext.time_base.den;
            FILE *file;
            stringstream filename;
            filename << "C:\\Bipul\\" << pts << ".raw";

            file = fopen(filename.str().c_str(), "wb");
            fwrite(&rgbData[0], 1, rgbData.size(), file);
            fclose(file);

            fwrite(&rgbData[0], 1, rgbData.size(), _videoOutputFile);
        }
    }

    return decodedSize;
}


void SeekAndTranscode::TranscodeIntoFile()
{
    AVFrame* frame = NULL;
    AVPacket packet;
    int videoSeeks = 0;
    int frameCount = 0;
    int framerate = 24;
    try
    {
        frame = av_frame_alloc();
        if (!frame)
        {
            fprintf(stderr, "\nCould not allocate frame for decoding\n");
            exit(1);
        }

        av_init_packet(&packet);
        packet.data = NULL;
        packet.size = 0;

        while (av_read_frame(_formatContext, &packet) >= 0)
        {
            if(packet.stream_index == _videoStreamIndex)
            {
                frameCount++;
                if(frameCount % (10*framerate) == 0)
                {
                    if(videoSeeks == 1)
                        break;
                    av_seek_frame(_formatContext, -1, _seekPosition * AV_TIME_BASE, 0);
                    videoSeeks++;
                    continue;
                }
            }
            AVPacket originalPacket = packet;
            do
            {
                int status = _TranscodePacket(packet, frame);

                if (status < 0)
                    break;
                packet.data += status;
                packet.size -= status;
            } while (packet.size > 0);
            av_packet_unref(&originalPacket);
        }

        if (frame)
        {
            av_frame_free(&frame);
        }

        swr_free(&_resampler);
    }
    catch(const exception& e)
    {
        fprintf(stderr, "\n%s\n", e.what());
        exit(1);
    }
}

此版本的 FFmpeg 是否存在已知问题?这在以后的版本中修复了吗?有什么我做错了吗?任何线索将不胜感激。

【问题讨论】:

    标签: video ffmpeg


    【解决方案1】:

    在继续从流中读取更多帧之前,您需要刷新自己的缓冲区并在内部刷新 ffmpegs 缓冲区。

    avcodec_flush_buffers(myAVCodecContext); // do this for all your streams that are opened
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 2013-09-21
      • 1970-01-01
      • 2020-05-08
      • 1970-01-01
      • 2012-08-31
      相关资源
      最近更新 更多