From 2b21a08f89bbf5ccff935ada6b5bbe42501f18c4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 16 Jul 2019 20:20:25 -0700 Subject: Receive video frames in a loop --- examples/alffplay.cpp | 90 ++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 40 deletions(-) (limited to 'examples') diff --git a/examples/alffplay.cpp b/examples/alffplay.cpp index ccdfd51f..466c4576 100644 --- a/examples/alffplay.cpp +++ b/examples/alffplay.cpp @@ -552,19 +552,21 @@ int AudioState::decodeFrame() AVPacket *lastpkt{}; while((lastpkt=mPackets.getPacket(lock)) != nullptr) { - int ret{avcodec_send_packet(mCodecCtx.get(), lastpkt)}; + const int ret{avcodec_send_packet(mCodecCtx.get(), lastpkt)}; if(ret == AVERROR(EAGAIN)) break; + if(ret < 0) + std::cerr<< "Failed to send packet: "<nb_samples <= 0) @@ -1179,7 +1181,7 @@ void VideoState::updateVideo(SDL_Window *screen, SDL_Renderer *renderer) mFinalUpdate = true; mPictQRead.store(read_idx, std::memory_order_release); std::unique_lock{mPictQMutex}.unlock(); - mPictQCond.notify_all(); + mPictQCond.notify_one(); return; } @@ -1187,7 +1189,7 @@ void VideoState::updateVideo(SDL_Window *screen, SDL_Renderer *renderer) { mPictQRead.store(read_idx, std::memory_order_release); std::unique_lock{mPictQMutex}.unlock(); - mPictQCond.notify_all(); + mPictQCond.notify_one(); /* allocate or resize the buffer! */ bool fmt_updated{false}; @@ -1287,7 +1289,7 @@ void VideoState::updateVideo(SDL_Window *screen, SDL_Renderer *renderer) { mFinalUpdate = true; std::unique_lock{mPictQMutex}.unlock(); - mPictQCond.notify_all(); + mPictQCond.notify_one(); } } } @@ -1305,57 +1307,65 @@ int VideoState::handler() while(!mMovie.mQuit.load(std::memory_order_relaxed)) { - size_t write_idx{mPictQWrite.load(std::memory_order_relaxed)}; - Picture *vp{&mPictQ[write_idx]}; - { std::unique_lock lock{mPackets.getMutex()}; AVPacket *lastpkt{}; while((lastpkt=mPackets.getPacket(lock)) != nullptr) { - int ret{avcodec_send_packet(mCodecCtx.get(), lastpkt)}; + const int ret{avcodec_send_packet(mCodecCtx.get(), lastpkt)}; if(ret == AVERROR(EAGAIN)) break; + if(ret < 0) + std::cerr<< "Failed to send packet: "<mFrame.get()}; - int ret{avcodec_receive_frame(mCodecCtx.get(), decoded_frame)}; - if(ret == AVERROR_EOF) break; - if(ret < 0) + + while(!mMovie.mQuit.load(std::memory_order_relaxed)) { - std::cerr<< "Failed to decode frame: "<mFrame.get()}; + const int ret{avcodec_receive_frame(mCodecCtx.get(), decoded_frame)}; + if(ret == AVERROR_EOF) goto finished; + if(ret == AVERROR(EAGAIN)) break; + if(ret < 0) + { + std::cerr<< "Failed to receive frame: "<best_effort_timestamp != AV_NOPTS_VALUE) - mCurrentPts = std::chrono::duration_cast( - seconds_d64{av_q2d(mStream->time_base)*decoded_frame->best_effort_timestamp}); - vp->mPts = mCurrentPts; + /* Get the PTS for this frame. */ + if(decoded_frame->best_effort_timestamp != AV_NOPTS_VALUE) + mCurrentPts = std::chrono::duration_cast( + seconds_d64{av_q2d(mStream->time_base)*decoded_frame->best_effort_timestamp}); + vp->mPts = mCurrentPts; - /* Update the video clock to the next expected PTS. */ - auto frame_delay = av_q2d(mCodecCtx->time_base); - frame_delay += decoded_frame->repeat_pict * (frame_delay * 0.5); - mCurrentPts += std::chrono::duration_cast(seconds_d64{frame_delay}); + /* Update the video clock to the next expected PTS. */ + auto frame_delay = av_q2d(mCodecCtx->time_base); + frame_delay += decoded_frame->repeat_pict * (frame_delay * 0.5); + mCurrentPts += std::chrono::duration_cast(seconds_d64{frame_delay}); - /* Put the frame in the queue to be loaded into a texture and displayed - * by the rendering thread. - */ - write_idx = (write_idx+1)%mPictQ.size(); - mPictQWrite.store(write_idx, std::memory_order_release); + /* Put the frame in the queue to be loaded into a texture and + * displayed by the rendering thread. + */ + write_idx = (write_idx+1)%mPictQ.size(); + mPictQWrite.store(write_idx, std::memory_order_release); - if(write_idx == mPictQRead.load(std::memory_order_acquire)) - { - /* Wait until we have space for a new pic */ - std::unique_lock lock{mPictQMutex}; - while(write_idx == mPictQRead.load(std::memory_order_acquire) && - !mMovie.mQuit.load(std::memory_order_relaxed)) - mPictQCond.wait(lock); + if(write_idx == mPictQRead.load(std::memory_order_acquire)) + { + /* Wait until we have space for a new pic */ + std::unique_lock lock{mPictQMutex}; + while(write_idx == mPictQRead.load(std::memory_order_acquire) && + !mMovie.mQuit.load(std::memory_order_relaxed)) + mPictQCond.wait(lock); + } } } +finished: mEOS = true; std::unique_lock lock{mPictQMutex}; -- cgit v1.2.3