1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef TEST_TESTSUPPORT_FRAME_READER_H_
#define TEST_TESTSUPPORT_FRAME_READER_H_
#include <stdio.h>
#include <memory>
#include <optional>
#include <string>
#include "api/scoped_refptr.h"
#include "api/video/i420_buffer.h"
#include "api/video/resolution.h"
namespace webrtc {
namespace test {
// Handles reading of I420 frames from video files.
class FrameReader {
public:
struct Ratio {
int num = 1;
int den = 1;
};
static constexpr Ratio kNoScale = Ratio({.num = 1, .den = 1});
virtual ~FrameReader() {}
// Reads and returns next frame. Returns `nullptr` if reading failed or end of
// stream is reached.
virtual scoped_refptr<I420Buffer> PullFrame() = 0;
// Reads and returns next frame. `frame_num` stores unwrapped frame number
// which can be passed to `ReadFrame` to re-read this frame later. Returns
// `nullptr` if reading failed or end of stream is reached.
virtual scoped_refptr<I420Buffer> PullFrame(int* frame_num) = 0;
// Reads and returns frame specified by `frame_num`. Returns `nullptr` if
// reading failed.
virtual scoped_refptr<I420Buffer> ReadFrame(int frame_num) = 0;
// Reads next frame, resizes and returns it. `frame_num` stores unwrapped
// frame number which can be passed to `ReadFrame` to re-read this frame
// later. `resolution` specifies resolution of the returned frame.
// `framerate_scale` specifies frame rate scale factor. Frame rate scaling is
// done by skipping or repeating frames.
virtual scoped_refptr<I420Buffer> PullFrame(int* frame_num,
Resolution resolution,
Ratio framerate_scale) = 0;
// Reads frame specified by `frame_num`, resizes and returns it. Returns
// `nullptr` if reading failed.
virtual scoped_refptr<I420Buffer> ReadFrame(int frame_num,
Resolution resolution) = 0;
// Total number of retrievable frames.
virtual int num_frames() const = 0;
};
class YuvFrameReaderImpl : public FrameReader {
public:
enum class RepeatMode { kSingle, kRepeat, kPingPong };
// Creates the frame reader for a YUV file specified by `filepath`.
// `resolution` specifies width and height of frames in pixels. `repeat_mode`
// specifies behaviour of the reader at reaching the end of file (stop, read
// it over from the beginning or read in reverse order). The file is assumed
// to exist, be readable and to contain at least 1 frame.
YuvFrameReaderImpl(std::string filepath,
Resolution resolution,
RepeatMode repeat_mode);
~YuvFrameReaderImpl() override;
virtual void Init();
scoped_refptr<I420Buffer> PullFrame() override;
scoped_refptr<I420Buffer> PullFrame(int* frame_num) override;
scoped_refptr<I420Buffer> PullFrame(int* frame_num,
Resolution resolution,
Ratio framerate_scale) override;
scoped_refptr<I420Buffer> ReadFrame(int frame_num) override;
scoped_refptr<I420Buffer> ReadFrame(int frame_num,
Resolution resolution) override;
int num_frames() const override { return num_frames_; }
protected:
class RateScaler {
public:
int Skip(Ratio framerate_scale);
private:
std::optional<int> ticks_;
};
const std::string filepath_;
Resolution resolution_;
const RepeatMode repeat_mode_;
int num_frames_;
int frame_num_;
int frame_size_bytes_;
int header_size_bytes_;
FILE* file_;
RateScaler framerate_scaler_;
};
class Y4mFrameReaderImpl : public YuvFrameReaderImpl {
public:
// Creates the frame reader for a Y4M file specified by `filepath`.
// `repeat_mode` specifies behaviour of the reader at reaching the end of file
// (stop, read it over from the beginning or read in reverse order). The file
// is assumed to exist, be readable and to contain at least 1 frame.
Y4mFrameReaderImpl(std::string filepath, RepeatMode repeat_mode);
void Init() override;
};
std::unique_ptr<FrameReader> CreateYuvFrameReader(std::string filepath,
Resolution resolution);
std::unique_ptr<FrameReader> CreateYuvFrameReader(
std::string filepath,
Resolution resolution,
YuvFrameReaderImpl::RepeatMode repeat_mode);
std::unique_ptr<FrameReader> CreateY4mFrameReader(std::string filepath);
std::unique_ptr<FrameReader> CreateY4mFrameReader(
std::string filepath,
YuvFrameReaderImpl::RepeatMode repeat_mode);
} // namespace test
} // namespace webrtc
#endif // TEST_TESTSUPPORT_FRAME_READER_H_
|