From 3984c7d52b3203c08f4e3256594d61c539db5329 Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Sun, 28 Jun 2015 13:03:31 +0200 Subject: [PATCH] Wraps two av functions in c++ --- lib/av/av.cpp | 25 +++++++++++++++++++++++++ lib/av/av.hpp | 5 +++++ lib/image_io.cpp | 20 +++++++++----------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/av/av.cpp b/lib/av/av.cpp index 992e444..9fd28c7 100644 --- a/lib/av/av.cpp +++ b/lib/av/av.cpp @@ -6,9 +6,15 @@ extern "C" { #include } +#include #include #include +// Was not yet defined in :( +static std::string operator "" s(const char *str, std::size_t len){ + return {str, len}; +} + namespace av { format_context format_open_input(const std::string& filename, AVInputFormat* format, AVDictionary** options){ @@ -98,4 +104,23 @@ namespace av { return crop(frame_clone(f), left, top, width, height); } + + bool codec_decode_video(codec_context& ctx, frame& f, const packet& pkt){ + int finished = 0; + int ret = avcodec_decode_video2(ctx.get(), f.get(), &finished, pkt.get()); + if (ret < 0) { + throw std::runtime_error("Error ["s + std::to_string(ret) + "] while decoding frame: "s + strerror(AVERROR(ret))); + } + return finished; + } + + void codec_decode_video_remaining(codec_context& ctx, frame& f){ + AVPacket pkt{0, 0, 0, 0, 0}; // data and size should be 0 + int finished = 0; + int ret = avcodec_decode_video2(ctx.get(), f.get(), &finished, &pkt); + if (ret < 0) { + throw std::runtime_error("Error ["s + std::to_string(ret) + "] while decoding remaining frame: "s + strerror(AVERROR(ret))); + } + } + } diff --git a/lib/av/av.hpp b/lib/av/av.hpp index 8da56f8..57a78c1 100644 --- a/lib/av/av.hpp +++ b/lib/av/av.hpp @@ -45,4 +45,9 @@ namespace av { void crop(frame & f, int left, int top, int width, int height); frame crop(frame && f, int left, int top, int width, int height); frame crop(frame const & f, int left, int top, int width, int height); + + + // + bool codec_decode_video(codec_context & ctx, frame & f, packet const & pkt); + void codec_decode_video_remaining(codec_context & ctx, frame & f); } diff --git a/lib/image_io.cpp b/lib/image_io.cpp index e2ce746..3c24b1f 100644 --- a/lib/image_io.cpp +++ b/lib/image_io.cpp @@ -55,23 +55,21 @@ av::frame open_image(std::string const & filename){ // things to read and decode it av::packet_buffer empty_packet; - int finished = 0; + bool need_extra_pass = true; while(auto packet = av::read_frame(format_context, empty_packet)) { if(packet->stream_index != 0) continue; - int ret = avcodec_decode_video2(codec_context.get(), frame.get(), &finished, packet.get()); - if (ret <= 0) { - printf("Error [%d] while decoding frame: %s\n", ret, strerror(AVERROR(ret))); - throw std::runtime_error("boem packet"); - } - // we only need the first frame - if(finished) break; + if(av::codec_decode_video(codec_context, frame, packet)) { + need_extra_pass = false; + break; + } } - // some decoders need extra passes - while(!finished) { - avcodec_decode_video2(codec_context.get(), frame.get(), &finished, &empty_packet); + // some decoders need an extra pass + // See the flag CODEC_CAP_DELAY for more info + if(need_extra_pass) { + av::codec_decode_video_remaining(codec_context, frame); } return frame;