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

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: Created 5 years, 1 month 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";
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 void NdkMediaCodecBridge::Stop() {
58 AMediaCodec_stop(media_codec_.get());
59 }
60
61 void NdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
62 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
63 int left, right, bottom, top;
64 bool has_left = AMediaFormat_getInt32(format, kMediaFormatKeyCropLeft, &left);
65 bool has_right =
66 AMediaFormat_getInt32(format, kMediaFormatKeyCropRight, &right);
67 bool has_bottom =
68 AMediaFormat_getInt32(format, kMediaFormatKeyCropBottom, &bottom);
69 bool has_top = AMediaFormat_getInt32(format, kMediaFormatKeyCropTop, &top);
70 if (has_left && has_right && has_bottom && has_top) {
71 *width = right - left + 1;
72 *height = top - bottom + 1;
73 } else {
74 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
75 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
76 }
77 }
78
79 int NdkMediaCodecBridge::GetOutputSamplingRate() {
80 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
81 int sample_rate;
82 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate);
83 return sample_rate;
84 }
85
86 MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
87 int index,
88 const uint8* data,
89 size_t data_size,
90 const base::TimeDelta& presentation_time) {
91 if (data_size > base::checked_cast<size_t>(kint32max))
92 return MEDIA_CODEC_ERROR;
93 if (data && !FillInputBuffer(index, data, data_size))
94 return MEDIA_CODEC_ERROR;
95
96 media_status_t status =
97 AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size,
98 presentation_time.InMicroseconds(), 0);
99 return TranslateMediaCodecStatus(status);
100 }
101
102 MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer(
103 int index,
104 const uint8* data,
105 size_t data_size,
106 const uint8* key_id,
107 int key_id_size,
108 const uint8* iv,
109 int iv_size,
110 const SubsampleEntry* subsamples,
111 int subsamples_size,
112 const base::TimeDelta& presentation_time) {
113 if (data_size > base::checked_cast<size_t>(kint32max))
114 return MEDIA_CODEC_ERROR;
115 if (key_id_size > 16 || iv_size > 16)
116 return MEDIA_CODEC_ERROR;
117 if (data && !FillInputBuffer(index, data, data_size))
118 return MEDIA_CODEC_ERROR;
119
120 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
121 std::vector<size_t> clear_data, encrypted_data;
122 if (subsamples_size == 0) {
123 DCHECK(!subsamples);
124 clear_data.push_back(0);
125 encrypted_data.push_back(data_size);
126 } else {
127 DCHECK_GT(subsamples_size, 0);
128 DCHECK(subsamples);
129 for (int i = 0; i < subsamples_size; ++i) {
130 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
131 if (subsamples[i].cypher_bytes >
132 static_cast<uint32>(std::numeric_limits<int32>::max())) {
133 return MEDIA_CODEC_ERROR;
134 }
135 clear_data.push_back(subsamples[i].clear_bytes);
136 encrypted_data.push_back(subsamples[i].cypher_bytes);
137 }
138 }
139
140 uint8_t key_array[16], iv_array[16];
141 memcpy(key_array, key_id, 16);
142 memcpy(iv_array, iv, 16);
143 AMediaCodecCryptoInfo* crypto_info =
144 AMediaCodecCryptoInfo_new(new_subsamples_size, key_array, iv_array,
145 AMEDIACODECRYPTOINFO_MODE_AES_CTR,
146 clear_data.data(), encrypted_data.data());
147
148 media_status_t status = AMediaCodec_queueSecureInputBuffer(
149 media_codec_.get(), index, 0, crypto_info,
150 presentation_time.InMicroseconds(), 0);
151 return TranslateMediaCodecStatus(status);
152 }
153
154 void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
155 AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0,
156 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
157 }
158
159 MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer(
160 const base::TimeDelta& timeout,
161 int* index) {
162 *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(),
163 timeout.InMicroseconds());
164 if (*index >= 0)
165 return MEDIA_CODEC_OK;
166 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
167 return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
168 else
169 return MEDIA_CODEC_ERROR;
170 }
171
172 MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer(
173 const base::TimeDelta& timeout,
174 int* index,
175 size_t* offset,
176 size_t* size,
177 base::TimeDelta* presentation_time,
178 bool* end_of_stream,
179 bool* key_frame) {
180 AMediaCodecBufferInfo buffer_info;
181 *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info,
182 timeout.InMicroseconds());
183 *offset = buffer_info.offset;
184 *size = buffer_info.size;
185 *presentation_time =
186 base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs);
187 if (end_of_stream)
188 *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
189 if (key_frame)
190 *key_frame = false; // This is deprecated.
191 if (*index >= 0)
192 return MEDIA_CODEC_OK;
193 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
194 return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
195 else
196 return MEDIA_CODEC_ERROR;
197 }
198
199 void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
200 AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render);
201 }
202
203 void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
204 uint8** data,
205 size_t* capacity) {
206 *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index,
207 capacity);
208 }
209
210 bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
211 size_t offset,
212 void* dst,
213 int dst_size) {
214 size_t capacity;
215 uint8_t* src_data =
216 AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
217
218 if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size))
219 return false;
220
221 memcpy(dst, src_data + offset, dst_size);
222 return true;
223 }
224
225 bool NdkMediaCodecBridge::StartInternal() {
226 return AMEDIA_OK == AMediaCodec_start(media_codec_.get());
227 }
228
229 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698