summaryrefslogtreecommitdiffstats
path: root/media/base/android/sdk_media_codec_bridge.h
blob: c495ffc93ff6a46cea7ab11f5f416157f7c29618 (plain)
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright (c) 2013 The Chromium 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 MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
#define MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_

#include <jni.h>
#include <stdint.h>

#include <set>
#include <string>

#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "media/base/android/media_codec_bridge.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/media_export.h"
#include "media/base/video_decoder_config.h"
#include "ui/gfx/geometry/size.h"

namespace media {

// This class implements MediaCodecBridge using android MediaCodec SDK APIs.
class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge {
 public:
  ~SdkMediaCodecBridge() override;

  // MediaCodecBridge implementations.
  MediaCodecStatus Reset() override;
  bool Start() override;
  void Stop() override;
  void GetOutputFormat(int* width, int* height) override;
  int GetOutputSamplingRate() override;
  MediaCodecStatus QueueInputBuffer(
      int index,
      const uint8_t* data,
      size_t data_size,
      const base::TimeDelta& presentation_time) override;
  using MediaCodecBridge::QueueSecureInputBuffer;
  MediaCodecStatus QueueSecureInputBuffer(
      int index,
      const uint8_t* data,
      size_t data_size,
      const std::vector<char>& key_id,
      const std::vector<char>& iv,
      const SubsampleEntry* subsamples,
      int subsamples_size,
      const base::TimeDelta& presentation_time) override;
  void QueueEOS(int input_buffer_index) override;
  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
                                      int* index) override;
  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
                                       int* index,
                                       size_t* offset,
                                       size_t* size,
                                       base::TimeDelta* presentation_time,
                                       bool* end_of_stream,
                                       bool* key_frame) override;
  void ReleaseOutputBuffer(int index, bool render) override;
  int GetOutputBuffersCount() override;
  size_t GetOutputBuffersCapacity() override;
  void GetInputBuffer(int input_buffer_index,
                      uint8_t** data,
                      size_t* capacity) override;
  bool CopyFromOutputBuffer(int index,
                            size_t offset,
                            void* dst,
                            int dst_size) override;

  static bool RegisterSdkMediaCodecBridge(JNIEnv* env);

 protected:
  SdkMediaCodecBridge(const std::string& mime,
                      bool is_secure,
                      MediaCodecDirection direction);

  // Called to get the buffer address given the output buffer index and offset.
  // This function returns the size of the output and |addr| is the pointer to
  // the address to read.
  int GetOutputBufferAddress(int index, size_t offset, void** addr);

  jobject media_codec() { return j_media_codec_.obj(); }
  MediaCodecDirection direction_;

 private:
  // Java MediaCodec instance.
  base::android::ScopedJavaGlobalRef<jobject> j_media_codec_;

  DISALLOW_COPY_AND_ASSIGN(SdkMediaCodecBridge);
};

// Class for handling audio decoding using android MediaCodec APIs.
// TODO(qinmin): implement the logic to switch between NDK and SDK
// MediaCodecBridge.
class MEDIA_EXPORT AudioCodecBridge : public SdkMediaCodecBridge {
 public:
  // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL
  // pointer otherwise.
  static AudioCodecBridge* Create(const AudioCodec& codec);

  // See MediaCodecUtil::IsKnownUnaccelerated().
  static bool IsKnownUnaccelerated(const AudioCodec& codec);

  // Start the audio codec bridge.
  bool ConfigureAndStart(const AudioCodec& codec,
                         int sample_rate,
                         int channel_count,
                         const uint8_t* extra_data,
                         size_t extra_data_size,
                         int64_t codec_delay_ns,
                         int64_t seek_preroll_ns,
                         bool play_audio,
                         jobject media_crypto) WARN_UNUSED_RESULT;

  // Plays the output buffer right away or save for later playback if |postpone|
  // is set to true. This call must be called after DequeueOutputBuffer() and
  // before ReleaseOutputBuffer. The data is extracted from the output buffers
  // using |index|, |size| and |offset|. Returns the playback head position
  // expressed in frames.
  // When |postpone| is set to true, the next PlayOutputBuffer() should have
  // postpone == false, and it will play two buffers: the postponed one and
  // the one identified by |index|.
  int64_t PlayOutputBuffer(int index,
                           size_t size,
                           size_t offset,
                           bool postpone = false);

  // Set the volume of the audio output.
  void SetVolume(double volume);

 private:
  explicit AudioCodecBridge(const std::string& mime);

  // Configure the java MediaFormat object with the extra codec data passed in.
  bool ConfigureMediaFormat(jobject j_format,
                            const AudioCodec& codec,
                            const uint8_t* extra_data,
                            size_t extra_data_size,
                            int64_t codec_delay_ns,
                            int64_t seek_preroll_ns);
};

// Class for handling video encoding/decoding using android MediaCodec APIs.
// TODO(qinmin): implement the logic to switch between NDK and SDK
// MediaCodecBridge.
class MEDIA_EXPORT VideoCodecBridge : public SdkMediaCodecBridge {
 public:
  // See MediaCodecUtil::IsKnownUnaccelerated().
  static bool IsKnownUnaccelerated(const VideoCodec& codec,
                                   MediaCodecDirection direction);

  // Create, start, and return a VideoCodecBridge decoder or NULL on failure.
  static VideoCodecBridge* CreateDecoder(
      const VideoCodec& codec,  // e.g. media::kCodecVP8
      bool is_secure,
      const gfx::Size& size,  // Output frame size.
      jobject surface,        // Output surface, optional.
      jobject media_crypto);  // MediaCrypto object, optional.

  // Create, start, and return a VideoCodecBridge encoder or NULL on failure.
  static VideoCodecBridge* CreateEncoder(
      const VideoCodec& codec,  // e.g. media::kCodecVP8
      const gfx::Size& size,    // input frame size
      int bit_rate,             // bits/second
      int frame_rate,           // frames/second
      int i_frame_interval,     // count
      int color_format);        // MediaCodecInfo.CodecCapabilities.

  void SetVideoBitrate(int bps);
  void RequestKeyFrameSoon();

  // Returns whether adaptive playback is supported for this object given
  // the new size.
  bool IsAdaptivePlaybackSupported(int width, int height);

  // Test-only method to set the return value of IsAdaptivePlaybackSupported().
  // Without this function, the return value of that function will be device
  // dependent. If |adaptive_playback_supported| is equal to 0, the return value
  // will be false. If |adaptive_playback_supported| is larger than 0, the
  // return value will be true.
  void set_adaptive_playback_supported_for_testing(
      int adaptive_playback_supported) {
    adaptive_playback_supported_for_testing_ = adaptive_playback_supported;
  }

 private:
  VideoCodecBridge(const std::string& mime,
                   bool is_secure,
                   MediaCodecDirection direction);

  int adaptive_playback_supported_for_testing_;
};

}  // namespace media

#endif  // MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_