blob: 91dab516fe4e7fdd177ede449038a9307e52a6bf [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ARC_CODEC_TEST_MEDIACODEC_ENCODER_H_
#define ARC_CODEC_TEST_MEDIACODEC_ENCODER_H_
// In Android N branch, off_t is 32-bit. Therefore we cannot compile the binary
// with _FILE_OFFSET_BITS=64. (crbug.com/945197)
#if ANDROID_VERSION < 0x0900 // Android 9.0 (Pie)
#if _FILE_OFFSET_BITS == 64
#error "oops, file _FILE_OFFSET_BITS == 64"
#elif defined(__USE_FILE_OFFSET64)
#error "oops, __USE_FILE_OFFSET64 is defined"
#endif // _FILE_OFFSET_BITS == 64
#endif // ANDROID_VERSION < 0x0900
#include <memory>
#include <string>
#include <media/NdkMediaCodec.h>
#include "arc/codec-test/common.h"
namespace android {
// Wrapper class to manipulate a MediaCodec video encoder.
class MediaCodecEncoder {
public:
// Checks the argument and create MediaCodecEncoder instance.
static std::unique_ptr<MediaCodecEncoder> Create(std::string input_path,
Size visible_size);
MediaCodecEncoder() = delete;
~MediaCodecEncoder();
using EncodeInputBufferCb = std::function<void(uint64_t /* time_us */)>;
// The callback function that is called when output buffer is ready.
using OutputBufferReadyCb = std::function<void(
const uint8_t* /* data */, const AMediaCodecBufferInfo& /* info */)>;
void SetEncodeInputBufferCb(const EncodeInputBufferCb& cb);
void SetOutputBufferReadyCb(const OutputBufferReadyCb& cb);
// Encoder manipulation methods.
// Rewind the frame index to the beginning of the input stream.
void Rewind();
// Wrapper of AMediaCodec_configure.
bool Configure(int32_t bitrate, int32_t framerate);
// Wrapper of AMediaCodec_start.
bool Start();
// Encode the test stream. After encoding, send EOS request to the
// encoder. Return true if EOS output buffer is received.
bool Encode();
// Wrapper of AMediaCodec_stop.
bool Stop();
// Setter and getter method of |num_encoded_frames_|;
void set_num_encoded_frames(size_t num_encoded_frames);
size_t num_encoded_frames() const;
// Setter method of |run_at_fps_|.
void set_run_at_fps(bool run_at_fps);
private:
MediaCodecEncoder(AMediaCodec* codec,
std::unique_ptr<InputFileStream> inputFile,
Size size,
size_t bufferSize,
size_t numTotalFrames);
// Read the content from the |input_file_| and feed into the input buffer.
// |index| is the index of the target input buffer.
bool FeedInputBuffer(size_t index);
// Feed an empty buffer with EOS flag.
// |index| is the index of the target input buffer.
bool FeedEOSInputBuffer(size_t index);
// Receive the output buffer and write into the |mOutputFile|.
// |index| is the index of the target output buffer.
// |info| is the buffer info of the target output buffer.
bool ReceiveOutputBuffer(size_t index, const AMediaCodecBufferInfo& info);
// The resolution of the input video stream.
const Size kVisibleSize;
// The buffer size of one frame, i.e. (width * height * 1.5) because now
// only YUV I420 is supported.
const size_t kBufferSize;
// The frame number of the input video stream.
const size_t kNumTotalFrames;
// The target mediacodec encoder.
AMediaCodec* codec_;
// The number of frames to encode.
size_t num_encoded_frames_;
// The input video raw stream file. The file size must be the multiple of
// |kBufferSize|.
std::unique_ptr<InputFileStream> input_file_;
// The target output bitrate.
int bitrate_ = 192000;
// The target output framerate.
int framerate_ = 30;
// Encode the data at the |framerate_|.
bool run_at_fps_ = false;
// The callback function which is called right before queueing one input
// buffer.
EncodeInputBufferCb encode_input_buffer_cb_;
// The callback function which is called when an output buffer is ready.
OutputBufferReadyCb output_buffer_ready_cb_;
// The frame index that indicates which frame is sent to the encoder at
// next round.
size_t input_frame_index_ = 0;
};
} // namespace android
#endif // ARC_CODEC_TEST_MEDIACODEC_ENCODER_H_