1 // Copyright 2019 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 C2_E2E_TEST_MEDIACODEC_DECODER_H_ 6 #define C2_E2E_TEST_MEDIACODEC_DECODER_H_ 7 8 #include <condition_variable> 9 #include <memory> 10 #include <mutex> 11 #include <queue> 12 #include <string> 13 #include <thread> 14 #include <vector> 15 16 #include <media/NdkMediaCodec.h> 17 18 #include "common.h" 19 #include "encoded_data_helper.h" 20 21 namespace android { 22 23 // Wrapper class to manipulate a MediaCodec video decoder. 24 class MediaCodecDecoder { 25 public: 26 // Checks the argument and create MediaCodecDecoder instance. 27 static std::unique_ptr<MediaCodecDecoder> Create(const std::string& input_path, 28 VideoCodecProfile profile, bool use_sw_decoder, 29 const Size& video_size, int frame_rate, 30 ANativeWindow* surface, bool renderOnRelease, 31 bool loop, bool use_fake_renderer); 32 33 MediaCodecDecoder() = delete; 34 ~MediaCodecDecoder(); 35 36 // The callback function that is called when output buffer is ready. Note that 37 // the buffer will be null if the decoder is in surface mode. 38 using OutputBufferReadyCb = std::function<void( 39 const uint8_t* /* data */, size_t /* buffer_size */, int /* output_index */)>; 40 void AddOutputBufferReadyCb(const OutputBufferReadyCb& cb); 41 42 // The callback function that is called when output format is changed. 43 using OutputFormatChangedCb = 44 std::function<void(const Size& /* coded_size */, const Size& /* visible_size */, 45 int32_t /* color_format */)>; 46 void AddOutputFormatChangedCb(const OutputFormatChangedCb& cb); 47 48 // Decoder manipulation methods. 49 50 // Rewind the input stream to the first frame as well as frame index. 51 void Rewind(); 52 53 // Wrapper of AMediaCodec_configure. 54 bool Configure(); 55 56 // Wrapper of AMediaCodec_start. 57 bool Start(); 58 59 // Decode the input stream. After decoding, send EOS request to the decoder. 60 // Return true if EOS output buffer is received. 61 bool Decode(); 62 63 // Wrapper of AMediaCodec_stop. 64 bool Stop(); 65 StopLooping()66 void StopLooping() { looping_ = false; } 67 68 double dropped_frame_rate() const; 69 70 void OnAsyncInputAvailable(int32_t idx); 71 void OnAsyncOutputAvailable(int32_t idx, AMediaCodecBufferInfo* info); 72 void OnAsyncFormatChanged(AMediaFormat* format); 73 74 void FakeRenderLoop(); 75 76 private: 77 enum CodecEventType { INPUT_AVAILABLE, OUTPUT_AVAILABLE, FORMAT_CHANGED, FAKE_FRAME_RENDERED }; 78 struct CodecEvent { 79 CodecEventType type; 80 int32_t idx; 81 AMediaCodecBufferInfo info; 82 }; 83 84 MediaCodecDecoder(AMediaCodec* codec, std::unique_ptr<EncodedDataHelper> encoded_data_helper, 85 VideoCodecType type, const Size& size, int frame_rate, ANativeWindow* surface, 86 bool renderOnRelease, bool loop, bool use_fake_renderer); 87 88 // Enum class of the status of dequeueing output buffer. 89 enum class DequeueStatus { RETRY, SUCCESS, FAILURE }; 90 91 // Fill all available input buffers and enqueue. 92 bool EnqueueInputBuffers(int32_t idx); 93 94 // Try to dequeue one output buffer and return DequeueStatus. 95 bool DequeueOutputBuffer(int32_t idx, AMediaCodecBufferInfo info); 96 97 // Read the sample data from AMediaExtractor or CSD data and feed into the 98 // input buffer. 99 // |index| is the index of the target input buffer. 100 bool FeedInputBuffer(size_t index); 101 102 // Feed an empty buffer with EOS flag. 103 // |index| is the index of the target input buffer. 104 bool FeedEOSInputBuffer(size_t index); 105 106 // Receive the output buffer and make mOutputBufferReadyCb callback if given. 107 // |index| is the index of the target output buffer. 108 // |info| is the buffer info of the target output buffer. 109 bool ReceiveOutputBuffer(int32_t index, const AMediaCodecBufferInfo& info, bool render_buffer); 110 111 // Get output format by AMediaCodec_getOutputFormat and make 112 // |output_format_changed_cb_| callback if given. 113 // Return false if required information is missing, e.g. width, color format. 114 bool GetOutputFormat(); 115 116 int64_t GetReleaseTimestampNs(size_t frame_order); 117 118 // The target mediacodec decoder. 119 AMediaCodec* codec_; 120 121 // The reference of EncodedDataHelper. 122 std::unique_ptr<EncodedDataHelper> encoded_data_helper_; 123 124 // The codec type of decoding. 125 VideoCodecType type_; 126 // The output video visible size. 127 Size input_visible_size_; 128 int frame_rate_; 129 130 // The list of callback functions which are called in order when a output 131 // buffer is ready. 132 std::vector<OutputBufferReadyCb> output_buffer_ready_cbs_; 133 // The list of callback functions that are called in order when output format 134 // is changed. 135 std::vector<OutputFormatChangedCb> output_format_changed_cbs_; 136 137 // The fragment index that indicates which frame is sent to the decoder at 138 // next round. 139 int64_t input_fragment_index_ = 0; 140 // The total number of received output buffers. Only used for logging. 141 int received_outputs_ = 0; 142 143 // The indication of input done. 144 bool input_done_ = false; 145 // The indication of output done. 146 bool output_done_ = false; 147 148 ANativeWindow* surface_ = nullptr; 149 bool render_on_release_ = false; 150 151 int64_t base_timestamp_ns_ = 0; 152 int32_t drop_frame_count_ = 0; 153 154 std::atomic<bool> looping_; 155 156 std::queue<CodecEvent> event_queue_; // guarded by event_queue_mut_ 157 std::mutex event_queue_mut_; 158 std::condition_variable event_queue_cv_; 159 160 std::atomic<bool> fake_renderer_running_; 161 std::thread fake_render_thread_; 162 std::mutex fake_render_mut_; 163 std::condition_variable fake_render_cv_; 164 std::queue<std::pair<int32_t, int64_t>> fake_render_frames_; 165 }; 166 167 } // namespace android 168 169 #endif // C2_E2E_TEST_MEDIACODEC_DECODER_H_ 170