寻求FFmpeg为旧帧提供新的数据包时间戳

时间:2017-08-17 07:49:42

标签: video ffmpeg

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

  1. 从给定的.mov文件中读取视频数据包
  2. 在解码视频10秒后寻找指定位置并继续10秒
  3. 在搜索之前和之后解码所有视频数据包并将其写入目标文件。
  4. 在此过程中,我还将所有收到的视频帧转储到原始图像文件中,使用原始数据包的PTS作为文件名。我注意到即使在搜索发生之后(通过时间戳的跳转来指出),搜索之后的前几帧包含新的时间戳,但是旧的帧(即,我没有搜索就会收到的帧)。

    These images illustrate the problem.

    以下是我正在使用的代码片段:

    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的已知问题吗?这是否已在以后的版本中修复?有什么我做错了吗?任何线索都将受到赞赏。

1 个答案:

答案 0 :(得分:0)

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

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