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

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: fix crazy linker issue 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 <limits>
11
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/native_library.h"
15 #include "base/strings/string_util.h"
16 #include "media/base/decrypt_config.h"
17
18 namespace {
19 const char kMediaFormatKeyCropLeft[] = "crop-left";
20 const char kMediaFormatKeyCropRight[] = "crop-right";
21 const char kMediaFormatKeyCropBottom[] = "crop-bottom";
22 const char kMediaFormatKeyCropTop[] = "crop-top";
23 }
24
25 namespace media {
26
27 // Translate media_status_t to MediaCodecStatus.
28 static MediaCodecStatus TranslateMediaCodecStatus(media_status_t status) {
29 switch (status) {
30 case AMEDIA_OK:
31 return MEDIA_CODEC_OK;
32 case AMEDIA_DRM_NEED_KEY:
33 return MEDIA_CODEC_NO_KEY;
34 default:
35 return MEDIA_CODEC_ERROR;
36 }
37 }
38
39 NdkMediaCodecBridge::~NdkMediaCodecBridge() {}
40
41 NdkMediaCodecBridge::NdkMediaCodecBridge(const std::string& mime,
42 bool is_secure,
43 MediaCodecDirection direction) {
44 if (base::StartsWith(mime, "video", base::CompareCase::SENSITIVE) &&
45 is_secure && direction == MEDIA_CODEC_DECODER) {
46 // TODO(qinmin): get the secure decoder name from java.
47 NOTIMPLEMENTED();
48 return;
49 }
50
51 if (direction == MEDIA_CODEC_DECODER)
52 media_codec_.reset(AMediaCodec_createDecoderByType(mime.c_str()));
53 else
54 media_codec_.reset(AMediaCodec_createEncoderByType(mime.c_str()));
55 }
56
57 MediaCodecStatus NdkMediaCodecBridge::Reset() {
58 media_status_t status = AMediaCodec_flush(media_codec_.get());
59 return TranslateMediaCodecStatus(status);
60 }
61
62 bool NdkMediaCodecBridge::Start() {
63 return AMEDIA_OK == AMediaCodec_start(media_codec_.get());
64 }
65
66 void NdkMediaCodecBridge::Stop() {
67 AMediaCodec_stop(media_codec_.get());
68 }
69
70 void NdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
71 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
72 int left, right, bottom, top;
73 bool has_left = AMediaFormat_getInt32(format, kMediaFormatKeyCropLeft, &left);
74 bool has_right =
75 AMediaFormat_getInt32(format, kMediaFormatKeyCropRight, &right);
76 bool has_bottom =
77 AMediaFormat_getInt32(format, kMediaFormatKeyCropBottom, &bottom);
78 bool has_top = AMediaFormat_getInt32(format, kMediaFormatKeyCropTop, &top);
79 if (has_left && has_right && has_bottom && has_top) {
80 // Use crop size as it is more accurate. right and bottom are inclusive.
81 *width = right - left + 1;
82 *height = top - bottom + 1;
83 } else {
84 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
85 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
86 }
87 }
88
89 int NdkMediaCodecBridge::GetOutputSamplingRate() {
90 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
91 int sample_rate = 0;
92 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate);
93 DCHECK(sample_rate != 0);
94 return sample_rate;
95 }
96
97 MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
98 int index,
99 const uint8_t* data,
100 size_t data_size,
101 const base::TimeDelta& presentation_time) {
102 if (data_size >
103 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
104 return MEDIA_CODEC_ERROR;
105 }
106 if (data && !FillInputBuffer(index, data, data_size))
107 return MEDIA_CODEC_ERROR;
108
109 media_status_t status =
110 AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size,
111 presentation_time.InMicroseconds(), 0);
112 return TranslateMediaCodecStatus(status);
113 }
114
115 MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer(
116 int index,
117 const uint8_t* data,
118 size_t data_size,
119 const std::vector<char>& key_id,
120 const std::vector<char>& iv,
121 const SubsampleEntry* subsamples,
122 int subsamples_size,
123 const base::TimeDelta& presentation_time) {
124 if (data_size >
125 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
126 return MEDIA_CODEC_ERROR;
127 }
128 if (key_id.size() > 16 || iv.size())
129 return MEDIA_CODEC_ERROR;
130 if (data && !FillInputBuffer(index, data, data_size))
131 return MEDIA_CODEC_ERROR;
132
133 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
134 std::vector<size_t> clear_data, encrypted_data;
135 if (subsamples_size == 0) {
136 DCHECK(!subsamples);
137 clear_data.push_back(0);
138 encrypted_data.push_back(data_size);
139 } else {
140 DCHECK_GT(subsamples_size, 0);
141 DCHECK(subsamples);
142 for (int i = 0; i < subsamples_size; ++i) {
143 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max());
144 if (subsamples[i].cypher_bytes >
145 static_cast<int32_t>(std::numeric_limits<int32_t>::max())) {
146 return MEDIA_CODEC_ERROR;
147 }
148 clear_data.push_back(subsamples[i].clear_bytes);
149 encrypted_data.push_back(subsamples[i].cypher_bytes);
150 }
151 }
152
153 AMediaCodecCryptoInfo* crypto_info = AMediaCodecCryptoInfo_new(
154 new_subsamples_size,
155 reinterpret_cast<uint8_t*>(const_cast<char*>(key_id.data())),
156 reinterpret_cast<uint8_t*>(const_cast<char*>(iv.data())),
157 AMEDIACODECRYPTOINFO_MODE_AES_CTR, clear_data.data(),
158 encrypted_data.data());
159
160 media_status_t status = AMediaCodec_queueSecureInputBuffer(
161 media_codec_.get(), index, 0, crypto_info,
162 presentation_time.InMicroseconds(), 0);
163 AMediaCodecCryptoInfo_delete(crypto_info);
164 return TranslateMediaCodecStatus(status);
165 }
166
167 void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
168 AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0,
169 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
170 }
171
172 MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer(
173 const base::TimeDelta& timeout,
174 int* index) {
175 *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(),
176 timeout.InMicroseconds());
177 if (*index >= 0)
178 return MEDIA_CODEC_OK;
179 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
180 return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
181 else
182 return MEDIA_CODEC_ERROR;
183 }
184
185 MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer(
186 const base::TimeDelta& timeout,
187 int* index,
188 size_t* offset,
189 size_t* size,
190 base::TimeDelta* presentation_time,
191 bool* end_of_stream,
192 bool* key_frame) {
193 AMediaCodecBufferInfo buffer_info;
194 *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info,
195 timeout.InMicroseconds());
196 *offset = buffer_info.offset;
197 *size = buffer_info.size;
198 *presentation_time =
199 base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs);
200 if (end_of_stream)
201 *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
202 if (key_frame)
203 *key_frame = false; // This is deprecated.
204 if (*index >= 0)
205 return MEDIA_CODEC_OK;
206 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
207 return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
208 else
209 return MEDIA_CODEC_ERROR;
210 }
211
212 void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
213 AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render);
214 }
215
216 void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
217 uint8_t** data,
218 size_t* capacity) {
219 *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index,
220 capacity);
221 }
222
223 bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
224 size_t offset,
225 void* dst,
226 int dst_size) {
227 size_t capacity;
228 uint8_t* src_data =
229 AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
230
231 if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size))
232 return false;
233
234 memcpy(dst, src_data + offset, dst_size);
235 return true;
236 }
237
238 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/ndk_media_codec_bridge.h ('k') | media/base/android/ndk_media_codec_wrapper.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698