]> git.sesse.net Git - nageru/blobdiff - ffmpeg_capture.h
In FFmpegCapture, frame decoding into its own function.
[nageru] / ffmpeg_capture.h
index 82ccfaf5a97aa810cbedab56c4690b2d1ff0f868..619266de9e74921adf2e0e8565319ca1cba63ec0 100644 (file)
 // Since we don't really know much about the video when building the chains,
 // there are some limitations. In particular, frames are always assumed to be
 // sRGB even if the video container says something else. We could probably
-// try to load the video on startup and pick out the parameters at that point
-// (which would probably also allow us to send Y'CbCr video through without
-// CPU conversion), but it would require some more plumbing, and it would also
-// fail if the file changes parameters midway, which is allowed in some formats.
+// try to load the video on startup and pick out the parameters at that point,
+// but it would require some more plumbing, and it would also fail if the file
+// changes parameters midway, which is allowed in some formats.
 //
 // There is currently no audio support.
 
 #include <string>
 #include <thread>
 
+#include <movit/ycbcr.h>
+
 #include "bmusb/bmusb.h"
+#include "ffmpeg_raii.h"
 #include "quittable_sleeper.h"
 
+struct AVFormatContext;
+
 class FFmpegCapture : public bmusb::CaptureInterface
 {
 public:
@@ -93,6 +97,14 @@ public:
                frame_callback = callback;
        }
 
+       // Used to get precise information about the Y'CbCr format used
+       // for a given frame. Only valid to call during the frame callback,
+       // and only when receiving a frame with pixel format PixelFormat_8BitYCbCrPlanar.
+       movit::YCbCrFormat get_current_frame_ycbcr_format() const
+       {
+               return current_frame_ycbcr_format;
+       }
+
        void set_dequeue_thread_callbacks(std::function<void()> init, std::function<void()> cleanup) override
        {
                dequeue_init_callback = init;
@@ -115,13 +127,13 @@ public:
        uint32_t get_current_video_mode() const override { return 0; }
 
        std::set<bmusb::PixelFormat> get_available_pixel_formats() const override {
-               return std::set<bmusb::PixelFormat>{ bmusb::PixelFormat_8BitBGRA };
+               return std::set<bmusb::PixelFormat>{ bmusb::PixelFormat_8BitBGRA, bmusb::PixelFormat_8BitYCbCrPlanar };
        }
        void set_pixel_format(bmusb::PixelFormat pixel_format) override {
-               assert(pixel_format == bmusb::PixelFormat_8BitBGRA);
+               this->pixel_format = pixel_format;
        }       
        bmusb::PixelFormat get_current_pixel_format() const override {
-               return bmusb::PixelFormat_8BitBGRA;
+               return pixel_format;
        }
 
        std::map<uint32_t, std::string> get_available_video_inputs() const override {
@@ -141,11 +153,20 @@ private:
        bool play_video(const std::string &pathname);
        void internal_rewind();
 
+       // Returns true if there was an error.
+       bool process_queued_commands(AVFormatContext *format_ctx, const std::string &pathname, timespec last_modified);
+
+       // Returns nullptr if no frame was decoded (e.g. EOF).
+       AVFrameWithDeleter decode_frame(AVFormatContext *format_ctx, AVCodecContext *codec_ctx, const std::string &pathname, int video_stream_index, bool *error);
+
        std::string description, filename;
        uint16_t timecode = 0;
        unsigned width, height;
+       bmusb::PixelFormat pixel_format = bmusb::PixelFormat_8BitBGRA;
+       movit::YCbCrFormat current_frame_ycbcr_format;
        bool running = false;
        int card_index = -1;
+       double rate = 1.0;
 
        bool has_dequeue_callbacks = false;
        std::function<void()> dequeue_init_callback = nullptr;