1 // Copyright 2020 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef ARC_CODEC_TEST_MEDIACODEC_ENCODER_H_
6 #define ARC_CODEC_TEST_MEDIACODEC_ENCODER_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include <media/NdkMediaCodec.h>
12 
13 #include "common.h"
14 
15 namespace android {
16 
17 // Wrapper class to manipulate a MediaCodec video encoder.
18 class MediaCodecEncoder {
19 public:
20     // Checks the argument and create MediaCodecEncoder instance.
21     static std::unique_ptr<MediaCodecEncoder> Create(std::string input_path, VideoCodecType type,
22                                                      Size visible_size, bool use_sw_encoder);
23     MediaCodecEncoder() = delete;
24     ~MediaCodecEncoder();
25 
26     using EncodeInputBufferCb = std::function<void(uint64_t /* time_us */)>;
27     // The callback function that is called when output buffer is ready.
28     using OutputBufferReadyCb =
29             std::function<void(const uint8_t* /* data */, const AMediaCodecBufferInfo& /* info */)>;
30     void SetEncodeInputBufferCb(const EncodeInputBufferCb& cb);
31     void SetOutputBufferReadyCb(const OutputBufferReadyCb& cb);
32 
33     // Encoder manipulation methods.
34     // Rewind the frame index to the beginning of the input stream.
35     void Rewind();
36 
37     // Wrapper of AMediaCodec_configure.
38     bool Configure(int32_t bitrate, int32_t framerate);
39 
40     // Wrapper of AMediaCodec_start.
41     bool Start();
42 
43     // Encode the test stream. After encoding, send EOS request to the
44     // encoder. Return true if EOS output buffer is received.
45     bool Encode();
46 
47     // Wrapper of AMediaCodec_stop.
48     bool Stop();
49 
50     // Setter and getter method of |num_encoded_frames_|;
51     void set_num_encoded_frames(size_t num_encoded_frames);
52     size_t num_encoded_frames() const;
53     // Setter method of |run_at_fps_|.
54     void set_run_at_fps(bool run_at_fps);
55 
56 private:
57     MediaCodecEncoder(AMediaCodec* codec, VideoCodecType type,
58                       std::unique_ptr<CachedInputFileStream> inputFile, Size size,
59                       size_t bufferSize, size_t numTotalFrames);
60 
61     // Read the content from the |input_file_| and feed into the input buffer.
62     // |index| is the index of the target input buffer.
63     bool FeedInputBuffer(size_t index);
64 
65     // Feed an empty buffer with EOS flag.
66     // |index| is the index of the target input buffer.
67     bool FeedEOSInputBuffer(size_t index);
68 
69     // Receive the output buffer and write into the |mOutputFile|.
70     // |index| is the index of the target output buffer.
71     // |info| is the buffer info of the target output buffer.
72     bool ReceiveOutputBuffer(size_t index, const AMediaCodecBufferInfo& info);
73 
74     // The resolution of the input video stream.
75     const Size kVisibleSize;
76     // The buffer size of one frame, i.e. (width * height * 1.5) because now
77     // only YUV I420 is supported.
78     const size_t kBufferSize;
79     // The frame number of the input video stream.
80     const size_t kNumTotalFrames;
81 
82     // The target mediacodec encoder.
83     AMediaCodec* codec_;
84     // The output codec type.
85     VideoCodecType type_;
86     // The number of frames to encode.
87     size_t num_encoded_frames_;
88     // The input video raw stream file. The file size must be the multiple of
89     // |kBufferSize|.
90     std::unique_ptr<CachedInputFileStream> input_file_;
91     // The target output bitrate.
92     int bitrate_ = 192000;
93     // The target output framerate.
94     int framerate_ = 30;
95     // Encode the data at the |framerate_|.
96     bool run_at_fps_ = false;
97 
98     // The callback function which is called right before queueing one input
99     // buffer.
100     EncodeInputBufferCb encode_input_buffer_cb_;
101     // The callback function which is called when an output buffer is ready.
102     OutputBufferReadyCb output_buffer_ready_cb_;
103 
104     // The frame index that indicates which frame is sent to the encoder at
105     // next round.
106     size_t input_frame_index_ = 0;
107 };
108 
109 }  // namespace android
110 
111 #endif  // ARC_CODEC_TEST_MEDIACODEC_ENCODER_H_
112