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
media / gpu / android / ndk_audio_encoder.h [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_ANDROID_NDK_AUDIO_ENCODER_H_
#define MEDIA_GPU_ANDROID_NDK_AUDIO_ENCODER_H_
#include <memory>
#include "base/android/requires_api.h"
#include "base/thread_annotations.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_encoder.h"
#include "media/base/audio_parameters.h"
#include "media/base/encoder_status.h"
#include "media/formats/mp4/aac.h"
#include "media/gpu/android/ndk_media_codec_wrapper.h"
#include "media/gpu/media_gpu_export.h"
namespace media {
class AudioTimestampHelper;
class ConvertingAudioFifo;
// This class uses the Android NDK (the AMediaCodec APIs) to encode audio.
// It only supports encoding AAC-LC.
// This class must be created, used and destroyed on the same runner; the
// unerlying NdkMediaCodecWrapper handles thread hops from the platform encoding
// thread to `task_runner_`.
// Note: calling flush() forces a lazy re-creation of the underlying
// `media_codec_` on the next Encode() call.
class REQUIRES_ANDROID_API(NDK_MEDIA_CODEC_MIN_API)
MEDIA_GPU_EXPORT NdkAudioEncoder : public AudioEncoder,
public NdkMediaCodecWrapper::Client {
public:
// `runner` - a task runner that will be used for all callbacks and external
// calls to this instance.
explicit NdkAudioEncoder(scoped_refptr<base::SequencedTaskRunner> runner);
NdkAudioEncoder(const NdkAudioEncoder&) = delete;
NdkAudioEncoder& operator=(const NdkAudioEncoder&) = delete;
~NdkAudioEncoder() override;
// AudioEncoder implementation.
void Initialize(const Options& options,
OutputCB output_callback,
EncoderStatusCB done_cb) override;
void Encode(std::unique_ptr<AudioBus> audio_bus,
base::TimeTicks capture_time,
EncoderStatusCB done_cb) override;
// Note: `media_codec_` will be destroyed after a successful flush, to be
// recreated with the same `options_` on the next Encode() call.
void Flush(EncoderStatusCB done_cb) override;
// MediaCodecWrapper::Client implementation.
void OnInputAvailable() override;
void OnOutputAvailable() override;
void OnError(media_status_t error) override;
private:
enum class FlushState {
kNone, // Not currently flushing.
kFlushingInputs, // There is remaining data in `fifo_` left to be fed.
kPendingEOS, // We are waiting for the EOS from the encoder.
kNeedsMediaCodec, // The flush completed, but we need to lazily recreate
// `media_codec_`.
};
bool CreateAndStartMediaCodec();
void ClearMediaCodec();
// Input functions.
void FeedAllInputs();
bool InputReady();
void FeedInput(const AudioBus* audio_bus);
// Flush() related functions.
void MaybeFeedEos();
void FeedEos();
void CompleteFlush();
// Output reading functions.
void DrainOutput();
bool DrainConfig();
// Logging and reporting functions.
void LogError(EncoderStatus status);
void LogAndReportError(EncoderStatus status, EncoderStatusCB done_cb);
void ReportPendingError(EncoderStatusCB done_cb);
void ReportOk(EncoderStatusCB done_cb);
SEQUENCE_CHECKER(sequence_checker_);
// A runner all for callbacks and externals calls to public methods.
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
// The format of encoded chunks outputted through `output_cb_`.
AudioParameters output_params_;
bool error_occurred_ = false;
// Delayed error status to be reported on the next Encode() or Flush() call.
std::optional<EncoderStatus> pending_error_status_;
// What portion of the flushing process we are in, if any.
FlushState flush_state_ GUARDED_BY_CONTEXT(sequence_checker_) =
NdkAudioEncoder::FlushState::kNone;
// Pending callback for Initialize(), Encode() or Flush().
EncoderStatusCB pending_flush_cb_;
// All input received from Encode() not yet sent to `media_codec_`.
std::unique_ptr<ConvertingAudioFifo> fifo_
GUARDED_BY_CONTEXT(sequence_checker_);
std::unique_ptr<AudioTimestampHelper> input_timestamp_tracker_
GUARDED_BY_CONTEXT(sequence_checker_);
std::unique_ptr<AudioTimestampHelper> output_timestamp_tracker_
GUARDED_BY_CONTEXT(sequence_checker_);
std::vector<uint8_t> codec_desc_;
std::vector<uint8_t> temp_header_buffer_;
mp4::AAC aac_config_parser_;
// Platform encoder which actually performs the encoding.
std::unique_ptr<NdkMediaCodecWrapper> media_codec_;
};
} // namespace media
#endif // MEDIA_GPU_ANDROID_NDK_AUDIO_ENCODER_H_