Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: media/base/android/ndk_media_codec_bridge.cc

Issue 1472943002: Refactor MediaCodecBridge to add support for NDK APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add media_codec_util.cc(h) Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium 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 #include "media/base/android/ndk_media_codec_bridge.h"
6
7 #include <media/NdkMediaError.h>
8 #include <media/NdkMediaFormat.h>
9
10 #include "base/strings/string_util.h"
11 #include "media/base/decrypt_config.h"
12
13 namespace {
14 const char* kMediaFormatKeyCropLeft = "crop-left";
15 const char* kMediaFormatKeyCropRight = "crop-right";
16 const char* kMediaFormatKeyCropBottom = "crop-bottom";
17 const char* kMediaFormatKeyCropTop = "crop-top";
xhwang 2015/11/30 23:11:50 we prefer const array to const pointer. where are
qinmin 2015/12/03 22:46:24 These are hidden keys, but you can check MediaCode
18 }
19
20 namespace media {
21
22 // Translate media_status_t to MediaCodecStatus.
23 static MediaCodecStatus TranslateMediaCodecStatus(media_status_t status) {
24 switch (status) {
25 case AMEDIA_OK:
26 return MEDIA_CODEC_OK;
27 case AMEDIA_DRM_NEED_KEY:
28 return MEDIA_CODEC_NO_KEY;
29 default:
30 return MEDIA_CODEC_ERROR;
31 }
32 }
33
34 NdkMediaCodecBridge::~NdkMediaCodecBridge() {}
35
36 NdkMediaCodecBridge::NdkMediaCodecBridge(const std::string& mime,
37 bool is_secure,
38 MediaCodecDirection direction) {
39 if (base::StartsWith(mime, "video", base::CompareCase::SENSITIVE) &&
40 is_secure && direction == MEDIA_CODEC_DECODER) {
41 // TODO(qinmin): get the secure decoder name from java.
42 NOTIMPLEMENTED();
43 return;
44 }
45
46 if (direction == MEDIA_CODEC_DECODER)
47 media_codec_.reset(AMediaCodec_createDecoderByType(mime.c_str()));
48 else
49 media_codec_.reset(AMediaCodec_createEncoderByType(mime.c_str()));
50 }
51
52 MediaCodecStatus NdkMediaCodecBridge::Reset() {
53 media_status_t status = AMediaCodec_flush(media_codec_.get());
54 return TranslateMediaCodecStatus(status);
55 }
56
57 bool NdkMediaCodecBridge::Start() {
58 return AMEDIA_OK == AMediaCodec_start(media_codec_.get());
59 }
60
61 void NdkMediaCodecBridge::Stop() {
62 AMediaCodec_stop(media_codec_.get());
63 }
64
65 void NdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
66 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
67 int left, right, bottom, top;
68 bool has_left = AMediaFormat_getInt32(format, kMediaFormatKeyCropLeft, &left);
69 bool has_right =
70 AMediaFormat_getInt32(format, kMediaFormatKeyCropRight, &right);
71 bool has_bottom =
72 AMediaFormat_getInt32(format, kMediaFormatKeyCropBottom, &bottom);
73 bool has_top = AMediaFormat_getInt32(format, kMediaFormatKeyCropTop, &top);
74 if (has_left && has_right && has_bottom && has_top) {
75 *width = right - left + 1;
76 *height = top - bottom + 1;
xhwang 2015/11/30 23:11:50 so "right" and "bottom" are inclusive? maybe worth
qinmin 2015/12/03 22:46:23 Done.
77 } else {
78 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
xhwang 2015/11/30 23:11:50 Q: Why we can't always use AMEDIAFORMAT_KEY_WIDTH?
qinmin 2015/12/03 22:46:24 It is not as accurate as crop_width, see b/1822476
79 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
80 }
81 }
82
83 int NdkMediaCodecBridge::GetOutputSamplingRate() {
84 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
85 int sample_rate;
86 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate);
xhwang 2015/11/30 23:11:50 what if this returns false?
qinmin 2015/12/03 22:46:24 This is a mandatory key, so it should never return
87 return sample_rate;
88 }
89
90 MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
91 int index,
92 const uint8* data,
93 size_t data_size,
94 const base::TimeDelta& presentation_time) {
95 if (data_size > base::checked_cast<size_t>(kint32max))
96 return MEDIA_CODEC_ERROR;
97 if (data && !FillInputBuffer(index, data, data_size))
98 return MEDIA_CODEC_ERROR;
99
100 media_status_t status =
101 AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size,
102 presentation_time.InMicroseconds(), 0);
103 return TranslateMediaCodecStatus(status);
104 }
105
106 MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer(
107 int index,
108 const uint8* data,
109 size_t data_size,
110 const uint8* key_id,
111 int key_id_size,
112 const uint8* iv,
113 int iv_size,
114 const SubsampleEntry* subsamples,
115 int subsamples_size,
116 const base::TimeDelta& presentation_time) {
117 if (data_size > base::checked_cast<size_t>(kint32max))
118 return MEDIA_CODEC_ERROR;
119 if (key_id_size > 16 || iv_size > 16)
120 return MEDIA_CODEC_ERROR;
121 if (data && !FillInputBuffer(index, data, data_size))
122 return MEDIA_CODEC_ERROR;
123
124 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
125 std::vector<size_t> clear_data, encrypted_data;
126 if (subsamples_size == 0) {
127 DCHECK(!subsamples);
128 clear_data.push_back(0);
129 encrypted_data.push_back(data_size);
130 } else {
131 DCHECK_GT(subsamples_size, 0);
132 DCHECK(subsamples);
133 for (int i = 0; i < subsamples_size; ++i) {
134 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
135 if (subsamples[i].cypher_bytes >
136 static_cast<uint32>(std::numeric_limits<int32>::max())) {
137 return MEDIA_CODEC_ERROR;
138 }
139 clear_data.push_back(subsamples[i].clear_bytes);
140 encrypted_data.push_back(subsamples[i].cypher_bytes);
141 }
142 }
143
144 uint8_t key_array[16], iv_array[16];
145 memcpy(key_array, key_id, 16);
146 memcpy(iv_array, iv, 16);
xhwang 2015/11/30 23:11:50 The caller actually has the key and iv as vectors.
qinmin 2015/12/03 22:46:24 Done.
147 AMediaCodecCryptoInfo* crypto_info =
148 AMediaCodecCryptoInfo_new(new_subsamples_size, key_array, iv_array,
149 AMEDIACODECRYPTOINFO_MODE_AES_CTR,
150 clear_data.data(), encrypted_data.data());
151
152 media_status_t status = AMediaCodec_queueSecureInputBuffer(
153 media_codec_.get(), index, 0, crypto_info,
154 presentation_time.InMicroseconds(), 0);
155 return TranslateMediaCodecStatus(status);
156 }
157
158 void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
159 AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0,
160 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
161 }
162
163 MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer(
164 const base::TimeDelta& timeout,
165 int* index) {
166 *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(),
167 timeout.InMicroseconds());
168 if (*index >= 0)
169 return MEDIA_CODEC_OK;
170 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
171 return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
172 else
173 return MEDIA_CODEC_ERROR;
174 }
175
176 MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer(
177 const base::TimeDelta& timeout,
178 int* index,
179 size_t* offset,
180 size_t* size,
181 base::TimeDelta* presentation_time,
182 bool* end_of_stream,
183 bool* key_frame) {
184 AMediaCodecBufferInfo buffer_info;
185 *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info,
186 timeout.InMicroseconds());
187 *offset = buffer_info.offset;
188 *size = buffer_info.size;
189 *presentation_time =
190 base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs);
191 if (end_of_stream)
192 *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
193 if (key_frame)
194 *key_frame = false; // This is deprecated.
195 if (*index >= 0)
196 return MEDIA_CODEC_OK;
197 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
198 return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
199 else
200 return MEDIA_CODEC_ERROR;
201 }
202
203 void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
204 AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render);
205 }
206
207 void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
208 uint8** data,
209 size_t* capacity) {
210 *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index,
211 capacity);
212 }
213
214 bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
215 size_t offset,
216 void* dst,
217 int dst_size) {
218 size_t capacity;
219 uint8_t* src_data =
220 AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
221
222 if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size))
223 return false;
224
225 memcpy(dst, src_data + offset, dst_size);
226 return true;
227 }
228
229 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698