<br />I'm having trouble reading video packets after seeking within a video.  I seem to have no problem reading reading video packets if I just start at the begining of the stream and scan every packet in order, but the below code is not working.<br /><br />I'm calling this from a timer that I want to grab the video frame closest to the time timeMs.  av_read_frame() is returning the value -541478725 the third time it gets called, which stops me from receiving and decoding the frame most of the time:<br /><br /><br />    QImage FfmpegMediaSource::getVideoFrame(int timeMs)<br />    {<br />        AVPacket packet;<br /><br />        //Seek to our goal time<br />        avcodec_flush_buffers(pCodecCtx);<br />        int64_t targetPts = timeMs * 1000;<br />        targetPts = av_rescale_q(targetPts, AV_TIME_BASE_Q,<br />                              pFormatCtx->streams[videoStream]->time_base);<br /><br />        int err = av_seek_frame(pFormatCtx, videoStream, targetPts, AVSEEK_FLAG_BACKWARD);<br /><br />        qDebug() << "targetPts " << targetPts;<br /><br />        //Read frame<br />        while (true)<br />        {<br />            err = av_read_frame(pFormatCtx, &packet);<br />            if (err == AVERROR(EAGAIN))<br />            {<br />                qDebug() << "Error reading packet: " << err;<br />                continue;<br />            }<br />            else if (err != 0)<br />            {<br />                qDebug() << "Error reading packet: " << err;<br />                break;<br />            }<br /><br />            if (packet.stream_index != videoStream)<br />                continue;<br /><br /><br />            err = avcodec_send_packet(pCodecCtx, &packet);<br />            if (err == AVERROR(EAGAIN))<br />            {<br />                continue;<br />            }<br />            else if (err != 0)<br />            {<br />                qDebug() << "Error sending packet: " << err;<br />            }<br /><br />            int64_t packetPts = packet.pts == AV_NOPTS_VALUE ? packet.dts : packet.pts;<br /><br />            qDebug() << "packet Pts " << packetPts << " flags " << packet.flags;<br /><br />            if (packetPts >= targetPts)<br />            {<br />                if (targetPts != 0)<br />                {<br />                    int j = 9;<br />                }<br /><br />                QImage img = readVideoFrame();<br />                return img;<br />            }<br /><br />        }<br /><br />        return QImage();<br />    }<br /><br />    QImage FfmpegMediaSource::readVideoFrame()<br />    {<br />        int err = 0;<br />        while (err >= 0)<br />        {<br />            err = avcodec_receive_frame(pCodecCtx, pFrame);<br />            if (err == AVERROR(EAGAIN) || err == AVERROR_EOF)<br />            {<br />                qDebug() << "Error decoding packet: " << err;<br />                break;<br />            }<br />            if (err < 0)<br />            {<br />                qDebug() << "Error decoding packet: " << err;<br />                break;<br />            }<br /><br />            // Convert the image from its native format to RGB<br />            sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data,<br />                pFrame->linesize, 0, pCodecCtx->height,<br />                pFrameRGB->data, pFrameRGB->linesize);<br /><br />            // Save the frame to disk<br />            if (_videoFrame.isNull() || _videoFrame.width() != pCodecCtx->width || _videoFrame.height() != pCodecCtx->height)<br />            {<br />                _videoFrame = QImage(pCodecCtx->width, pCodecCtx->height, QImage::Format_RGB32);<br />                _videoFrame.fill(Qt::white);<br />            }<br /><br />            for (int j = 0; j < pCodecCtx->height; ++j)<br />            {<br />                memcpy(_videoFrame.scanLine(j), pFrameRGB->data[0] + j * pFrameRGB->linesize[0], pCodecCtx->width * 4);<br />            }<br /><br />            if (_dumpNextFrame)<br />            {<br />                _videoFrame.save("d:\\tmp\\videoFrameDump.png");<br />                _dumpNextFrame = false;<br />            }<br /><br />            return _videoFrame;<br />        }<br /><br />        return QImage();<br />    }<br /><br /><br /><br />On the other hand, the below code which is very similar is working.  I run it just after opening the file and it saves the first hundred frames to disk correctly:<br /><br />    void FfmpegMediaSource::buildIndex()<br />    {<br />        //Scan through packets to find what's where<br />        AVPacket* packet;<br />        packet = av_packet_alloc();<br /><br />        int frame = 0;<br /><br />        int64_t keyPts = 0;<br />        while (av_read_frame(pFormatCtx, packet) >= 0)<br />        {<br />            int64_t pts = packet->pts == AV_NOPTS_VALUE ? packet->dts : packet->pts;<br /><br />            // Is this a packet from the video stream?<br />            if (packet->stream_index == videoStream)<br />            {<br />                AVRational time_base = pFormatCtx->streams[videoStream]->time_base;<br />                int presentationTime = pts * av_q2d(time_base) * 1000;<br /><br />                VideoFrame* videoFrame = new VideoFrame();<br /><br />                if (packet->flags & AV_PKT_FLAG_KEY)<br />                {<br />                    _videoKeyPst.append(pts);<br />                    videoFrame->isKeyframe = true;<br />                    keyPts = pts;<br />                }<br />                else<br />                    videoFrame->isKeyframe = false;<br /><br />                videoFrame->pts = pts;<br />                videoFrame->keyPts = keyPts;<br />                _videoFrameList.append(videoFrame);<br />                _videoPtsMap[pts] = videoFrame;<br /><br /><br />                if (frame < 100)<br />                {<br />                    int err = avcodec_send_packet(pCodecCtx, packet);<br />                    if (err != 0)<br />                    {<br />                        qDebug() << "Error sendsing packet: " << err;<br />                    }<br /><br />                    QImage img = readVideoFrame();<br />                    if (!img.isNull())<br />                    {<br />                        QString filename = "d:\\tmp\\ffmpegRick2\\videoDump_";<br />                        filename += QString::number(frame) + ".png";<br />                        qDebug() << "Dumping " << filename;<br />                        img.save(filename);<br />                    }<br />                }<br />                frame++;<br /><br />            }<br />            else if (packet->stream_index == audioStream)<br />            {<br />                ...<br />            }<br />        }<br /><br />        av_packet_free(&packet);<br /><br />        av_seek_frame(pFormatCtx, videoStream, 0, 0);<br />    }<br /><br /><br /><br />Any idea what I'm doing wrong?<br /><br /><br /><br />
<div>
<pre>---
http://www.kitfox.com</pre>
</div>