diff options
author | Chris Robinson <[email protected]> | 2019-07-23 02:19:02 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-07-23 02:38:07 -0700 |
commit | b8ac4b79e43d3ae60926f5aad7125d10b2d78ea7 (patch) | |
tree | 7e0da02383cc3768ef0f040b3fa790cf2e877f72 /examples/alffplay.cpp | |
parent | 8a9434c6238344e676e6defb74cea6bf6d62d401 (diff) |
Only send packets as needed
Diffstat (limited to 'examples/alffplay.cpp')
-rw-r--r-- | examples/alffplay.cpp | 88 |
1 files changed, 49 insertions, 39 deletions
diff --git a/examples/alffplay.cpp b/examples/alffplay.cpp index 62c1a908..fbbbdf89 100644 --- a/examples/alffplay.cpp +++ b/examples/alffplay.cpp @@ -212,20 +212,21 @@ public: mTotalSize = 0; } - void sendTo(AVCodecContext *codecctx) + int sendTo(AVCodecContext *codecctx) { std::unique_lock<std::mutex> lock{mMutex}; - AVPacket *lastpkt{}; - while((lastpkt=getPacket(lock)) != nullptr) + + AVPacket *pkt{getPacket(lock)}; + if(!pkt) return avcodec_send_packet(codecctx, nullptr); + + const int ret{avcodec_send_packet(codecctx, pkt)}; + if(ret != AVERROR(EAGAIN)) { - const int ret{avcodec_send_packet(codecctx, lastpkt)}; - if(ret == AVERROR(EAGAIN)) return; if(ret < 0) std::cerr<< "Failed to send packet: "<<ret <<std::endl; pop(); } - if(!lastpkt) - avcodec_send_packet(codecctx, nullptr); + return ret; } void setFinished() @@ -559,19 +560,16 @@ int AudioState::decodeFrame() { while(!mMovie.mQuit.load(std::memory_order_relaxed)) { - const int ret{avcodec_receive_frame(mCodecCtx.get(), mDecodedFrame.get())}; - if(ret < 0) + int ret; + while((ret=avcodec_receive_frame(mCodecCtx.get(), mDecodedFrame.get())) == AVERROR(EAGAIN)) + mPackets.sendTo(mCodecCtx.get()); + if(ret != 0) { if(ret == AVERROR_EOF) break; - if(ret != AVERROR(EAGAIN)) - { - std::cerr<< "Failed to receive frame: "<<ret <<std::endl; - break; - } + std::cerr<< "Failed to receive frame: "<<ret <<std::endl; + continue; } - mPackets.sendTo(mCodecCtx.get()); - if(mDecodedFrame->nb_samples <= 0) continue; @@ -998,7 +996,11 @@ int AudioState::handler() samples = av_malloc(buffer_len); /* Prefill the codec buffer. */ - mPackets.sendTo(mCodecCtx.get()); + do { + const int ret{mPackets.sendTo(mCodecCtx.get())}; + if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + break; + } while(1); srclock.lock(); if(alcGetInteger64vSOFT) @@ -1302,7 +1304,11 @@ int VideoState::handler() { pict.mFrame = AVFramePtr{av_frame_alloc()}; }); /* Prefill the codec buffer. */ - mPackets.sendTo(mCodecCtx.get()); + do { + const int ret{mPackets.sendTo(mCodecCtx.get())}; + if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + break; + } while(1); { std::lock_guard<std::mutex> _{mDispPtsMutex}; @@ -1317,30 +1323,34 @@ int VideoState::handler() /* Retrieve video frame. */ AVFrame *decoded_frame{vp->mFrame.get()}; - const int ret{avcodec_receive_frame(mCodecCtx.get(), decoded_frame)}; - if(ret == AVERROR_EOF) break; - if(ret == 0) + int ret; + while((ret=avcodec_receive_frame(mCodecCtx.get(), decoded_frame)) == AVERROR(EAGAIN)) + mPackets.sendTo(mCodecCtx.get()); + if(ret != 0) { - /* Get the PTS for this frame. */ - if(decoded_frame->best_effort_timestamp != AV_NOPTS_VALUE) - current_pts = std::chrono::duration_cast<nanoseconds>( - seconds_d64{av_q2d(mStream->time_base)*decoded_frame->best_effort_timestamp}); - vp->mPts = current_pts; - - /* 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); - current_pts += 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); - } - else if(ret != AVERROR(EAGAIN)) + if(ret == AVERROR_EOF) break; std::cerr<< "Failed to receive frame: "<<ret <<std::endl; + continue; + } + + /* Get the PTS for this frame. */ + if(decoded_frame->best_effort_timestamp != AV_NOPTS_VALUE) + current_pts = std::chrono::duration_cast<nanoseconds>( + seconds_d64{av_q2d(mStream->time_base)*decoded_frame->best_effort_timestamp}); + vp->mPts = current_pts; + + /* 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); + current_pts += 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); + /* Send a packet now so it's hopefully ready by the time it's needed. */ mPackets.sendTo(mCodecCtx.get()); if(write_idx == mPictQRead.load(std::memory_order_acquire)) |