diff options
author | Chris Robinson <[email protected]> | 2019-07-16 20:20:25 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-07-16 20:20:25 -0700 |
commit | 2b21a08f89bbf5ccff935ada6b5bbe42501f18c4 (patch) | |
tree | b86b94cebd4e8223a5f0c8de9019cbb2893e61b2 /examples | |
parent | 101e6412887c539b7409fdb016012900c18f5daf (diff) |
Receive video frames in a loop
Diffstat (limited to 'examples')
-rw-r--r-- | examples/alffplay.cpp | 90 |
1 files changed, 50 insertions, 40 deletions
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: "<<ret <<std::endl; mPackets.pop(); } if(!lastpkt) avcodec_send_packet(mCodecCtx.get(), nullptr); } - int ret{avcodec_receive_frame(mCodecCtx.get(), mDecodedFrame.get())}; + const int ret{avcodec_receive_frame(mCodecCtx.get(), mDecodedFrame.get())}; if(ret == AVERROR_EOF) break; if(ret < 0) { - std::cerr<< "Failed to decode frame: "<<ret <<std::endl; - return 0; + std::cerr<< "Failed to receive frame: "<<ret <<std::endl; + break; } if(mDecodedFrame->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<std::mutex>{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<std::mutex>{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<std::mutex>{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<std::mutex> 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: "<<ret <<std::endl; mPackets.pop(); } if(!lastpkt) avcodec_send_packet(mCodecCtx.get(), nullptr); } - /* Decode video frame */ - AVFrame *decoded_frame{vp->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: "<<ret <<std::endl; - continue; - } + size_t write_idx{mPictQWrite.load(std::memory_order_relaxed)}; + Picture *vp{&mPictQ[write_idx]}; + + /* Decode video frame. */ + AVFrame *decoded_frame{vp->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: "<<ret <<std::endl; + break; + } - /* Get the PTS for this frame. */ - if(decoded_frame->best_effort_timestamp != AV_NOPTS_VALUE) - mCurrentPts = std::chrono::duration_cast<nanoseconds>( - 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<nanoseconds>( + 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<nanoseconds>(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<nanoseconds>(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<std::mutex> 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<std::mutex> 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<std::mutex> lock{mPictQMutex}; |