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

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: addressing comments 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";
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 // Use crop size as it is more accurate. right and bottom are inclusive.
76 *width = right - left + 1;
77 *height = top - bottom + 1;
78 } else {
79 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
80 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
81 }
82 }
83
84 int NdkMediaCodecBridge::GetOutputSamplingRate() {
85 AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
86 int sample_rate = 0;
87 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate);
88 DCHECK(sample_rate != 0);
89 return sample_rate;
90 }
91
92 MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
93 int index,
94 const uint8* data,
95 size_t data_size,
96 const base::TimeDelta& presentation_time) {
97 if (data_size > base::checked_cast<size_t>(kint32max))
98 return MEDIA_CODEC_ERROR;
99 if (data && !FillInputBuffer(index, data, data_size))
100 return MEDIA_CODEC_ERROR;
101
102 media_status_t status =
103 AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size,
104 presentation_time.InMicroseconds(), 0);
105 return TranslateMediaCodecStatus(status);
106 }
107
108 MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer(
109 int index,
110 const uint8* data,
111 size_t data_size,
112 std::vector<char> key_id,
113 std::vector<char> iv,
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())
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 AMediaCodecCryptoInfo* crypto_info =
145 AMediaCodecCryptoInfo_new(new_subsamples_size,
146 reinterpret_cast<uint8*>(&key_id[0]),
xhwang 2015/12/04 18:07:58 we can use vector::data() now
qinmin 2015/12/04 20:26:04 Done.
147 reinterpret_cast<uint8*>(&iv[0]),
148 AMEDIACODECRYPTOINFO_MODE_AES_CTR,
149 clear_data.data(), encrypted_data.data());
150
151 media_status_t status = AMediaCodec_queueSecureInputBuffer(
152 media_codec_.get(), index, 0, crypto_info,
153 presentation_time.InMicroseconds(), 0);
154 return TranslateMediaCodecStatus(status);
155 }
156
157 void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
158 AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0,
159 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
160 }
161
162 MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer(
163 const base::TimeDelta& timeout,
164 int* index) {
165 *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(),
166 timeout.InMicroseconds());
167 if (*index >= 0)
168 return MEDIA_CODEC_OK;
169 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
170 return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
171 else
172 return MEDIA_CODEC_ERROR;
173 }
174
175 MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer(
176 const base::TimeDelta& timeout,
177 int* index,
178 size_t* offset,
179 size_t* size,
180 base::TimeDelta* presentation_time,
181 bool* end_of_stream,
182 bool* key_frame) {
183 AMediaCodecBufferInfo buffer_info;
184 *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info,
185 timeout.InMicroseconds());
186 *offset = buffer_info.offset;
187 *size = buffer_info.size;
188 *presentation_time =
189 base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs);
190 if (end_of_stream)
191 *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
192 if (key_frame)
193 *key_frame = false; // This is deprecated.
194 if (*index >= 0)
195 return MEDIA_CODEC_OK;
196 else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
197 return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
198 else
199 return MEDIA_CODEC_ERROR;
200 }
201
202 void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
203 AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render);
204 }
205
206 void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
207 uint8** data,
208 size_t* capacity) {
209 *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index,
210 capacity);
211 }
212
213 bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
214 size_t offset,
215 void* dst,
216 int dst_size) {
217 size_t capacity;
218 uint8_t* src_data =
219 AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
220
221 if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size))
222 return false;
223
224 memcpy(dst, src_data + offset, dst_size);
225 return true;
226 }
227
228 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698