Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 | 183 |
| 184 scoped_ptr<base::SharedMemory> shm( | 184 scoped_ptr<base::SharedMemory> shm( |
| 185 new base::SharedMemory(bitstream_buffer.handle(), true)); | 185 new base::SharedMemory(bitstream_buffer.handle(), true)); |
| 186 RETURN_ON_FAILURE(this, shm->Map(bitstream_buffer.size()), | 186 RETURN_ON_FAILURE(this, shm->Map(bitstream_buffer.size()), |
| 187 "Failed to SharedMemory::Map()", UNREADABLE_INPUT); | 187 "Failed to SharedMemory::Map()", UNREADABLE_INPUT); |
| 188 | 188 |
| 189 const base::TimeDelta presentation_timestamp = | 189 const base::TimeDelta presentation_timestamp = |
| 190 bitstream_buffer.presentation_timestamp(); | 190 bitstream_buffer.presentation_timestamp(); |
| 191 DCHECK(presentation_timestamp != media::kNoTimestamp()) | 191 DCHECK(presentation_timestamp != media::kNoTimestamp()) |
| 192 << "Bitstream buffers must have valid presentation timestamps"; | 192 << "Bitstream buffers must have valid presentation timestamps"; |
| 193 | |
| 193 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt | 194 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt |
| 194 // ref frames, but it's OK to overwrite it because we only expect a single | 195 // ref frames, but it's OK to overwrite it because we only expect a single |
| 195 // output frame to have that timestamp. AVDA clients only use the bitstream | 196 // output frame to have that timestamp. AVDA clients only use the bitstream |
| 196 // buffer id in the returned Pictures to map a bitstream buffer back to a | 197 // buffer id in the returned Pictures to map a bitstream buffer back to a |
| 197 // timestamp on their side, so either one of the bitstream buffer ids will | 198 // timestamp on their side, so either one of the bitstream buffer ids will |
| 198 // result in them finding the right timestamp. | 199 // result in them finding the right timestamp. |
| 199 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id(); | 200 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id(); |
| 200 | 201 |
| 201 status = media_codec_->QueueInputBuffer( | 202 const uint8_t* memory = static_cast<const uint8_t*>(shm->memory()); |
| 202 input_buf_index, static_cast<const uint8*>(shm->memory()), | 203 const std::string& key_id = bitstream_buffer.key_id(); |
| 203 bitstream_buffer.size(), presentation_timestamp); | 204 const std::string& iv = bitstream_buffer.iv(); |
| 205 const std::vector<media::SubsampleEntry>& subsamples = | |
| 206 bitstream_buffer.subsamples(); | |
| 207 | |
| 208 if (key_id.empty() || iv.empty()) { | |
| 209 status = media_codec_->QueueInputBuffer(input_buf_index, memory, | |
| 210 bitstream_buffer.size(), | |
| 211 presentation_timestamp); | |
| 212 } else { | |
| 213 status = media_codec_->QueueSecureInputBuffer( | |
|
dcheng
2015/10/23 00:44:47
Why doesn't this function just take std::string fo
Tima Vaisburd
2015/10/23 18:51:40
I think because this function was designed to work
| |
| 214 input_buf_index, memory, bitstream_buffer.size(), | |
| 215 reinterpret_cast<const uint8_t*>(key_id.data()), key_id.size(), | |
| 216 reinterpret_cast<const uint8_t*>(iv.data()), iv.size(), | |
| 217 subsamples.empty() ? nullptr : &subsamples[0], subsamples.size(), | |
| 218 presentation_timestamp); | |
| 219 } | |
| 220 | |
| 221 DVLOG(2) << __FUNCTION__ | |
| 222 << ": QueueInputBuffer: pts:" << presentation_timestamp | |
| 223 << " status:" << status; | |
| 224 | |
| 204 RETURN_ON_FAILURE(this, status == media::MEDIA_CODEC_OK, | 225 RETURN_ON_FAILURE(this, status == media::MEDIA_CODEC_OK, |
| 205 "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE); | 226 "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE); |
| 206 | 227 |
| 207 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output | 228 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output |
| 208 // will be returned from the bitstream buffer. However, MediaCodec API is | 229 // will be returned from the bitstream buffer. However, MediaCodec API is |
| 209 // not enough to guarantee it. | 230 // not enough to guarantee it. |
| 210 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to | 231 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to |
| 211 // keep getting more bitstreams from the client, and throttle them by using | 232 // keep getting more bitstreams from the client, and throttle them by using |
| 212 // |bitstreams_notified_in_advance_|. | 233 // |bitstreams_notified_in_advance_|. |
| 213 // TODO(dwkang): check if there is a way to remove this workaround. | 234 // TODO(dwkang): check if there is a way to remove this workaround. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 238 size_t offset = 0; | 259 size_t offset = 0; |
| 239 size_t size = 0; | 260 size_t size = 0; |
| 240 | 261 |
| 241 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutputBuffer"); | 262 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutputBuffer"); |
| 242 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 263 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
| 243 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, | 264 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, |
| 244 &eos, NULL); | 265 &eos, NULL); |
| 245 TRACE_EVENT_END2("media", "AVDA::DequeueOutputBuffer", "status", status, | 266 TRACE_EVENT_END2("media", "AVDA::DequeueOutputBuffer", "status", status, |
| 246 "presentation_timestamp (ms)", | 267 "presentation_timestamp (ms)", |
| 247 presentation_timestamp.InMilliseconds()); | 268 presentation_timestamp.InMilliseconds()); |
| 269 | |
| 270 DVLOG(3) << "AVDA::DequeueOutputBuffer: pts:" << presentation_timestamp | |
| 271 << " buf_index:" << buf_index << " offset:" << offset | |
| 272 << " size:" << size << " eos:" << eos; | |
| 273 | |
| 248 switch (status) { | 274 switch (status) { |
| 249 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 275 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 250 case media::MEDIA_CODEC_ERROR: | 276 case media::MEDIA_CODEC_ERROR: |
| 251 return false; | 277 return false; |
| 252 | 278 |
| 253 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 279 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
| 254 int32 width, height; | 280 int32 width, height; |
| 255 media_codec_->GetOutputFormat(&width, &height); | 281 media_codec_->GetOutputFormat(&width, &height); |
| 256 | 282 |
| 257 if (!picturebuffers_requested_) { | 283 if (!picturebuffers_requested_) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 280 case media::MEDIA_CODEC_OK: | 306 case media::MEDIA_CODEC_OK: |
| 281 DCHECK_GE(buf_index, 0); | 307 DCHECK_GE(buf_index, 0); |
| 282 break; | 308 break; |
| 283 | 309 |
| 284 default: | 310 default: |
| 285 NOTREACHED(); | 311 NOTREACHED(); |
| 286 break; | 312 break; |
| 287 } | 313 } |
| 288 } while (buf_index < 0); | 314 } while (buf_index < 0); |
| 289 | 315 |
| 290 if (eos) { | 316 // Normaly we assume that the decoder makes at most one output frame for each |
|
watk
2015/10/22 22:49:26
"Normally"
Tima Vaisburd
2015/10/23 18:51:40
Done.
| |
| 317 // distinct input timestamp. A VP9 alt ref frame is a case where an input | |
| 318 // buffer, with a possibly unique timestamp, will not result in a | |
| 319 // corresponding output frame. | |
| 320 | |
| 321 // However MediaCodecBridge uses timestamp correction and provides | |
| 322 // non-decreasing timestamp sequence, which might result in timestamp | |
| 323 // duplicates. Discard the frame if we cannot get corresponding buffer id. | |
| 324 | |
| 325 // Get the bitstream buffer id from the timestamp. | |
| 326 auto it = eos ? bitstream_buffers_in_decoder_.end() | |
| 327 : bitstream_buffers_in_decoder_.find(presentation_timestamp); | |
| 328 | |
| 329 if (it == bitstream_buffers_in_decoder_.end()) { | |
| 291 media_codec_->ReleaseOutputBuffer(buf_index, false); | 330 media_codec_->ReleaseOutputBuffer(buf_index, false); |
| 292 base::MessageLoop::current()->PostTask( | 331 base::MessageLoop::current()->PostTask( |
| 293 FROM_HERE, | 332 FROM_HERE, |
| 294 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | 333 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
| 295 weak_this_factory_.GetWeakPtr())); | 334 weak_this_factory_.GetWeakPtr())); |
| 296 } else { | 335 } else { |
| 297 // Get the bitstream buffer id from the timestamp. | |
| 298 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); | |
| 299 // Require the decoder to output at most one frame for each distinct input | |
| 300 // buffer timestamp. A VP9 alt ref frame is a case where an input buffer, | |
| 301 // with a possibly unique timestamp, will not result in a corresponding | |
| 302 // output frame. | |
| 303 CHECK(it != bitstream_buffers_in_decoder_.end()) | |
| 304 << "Unexpected output frame timestamp"; | |
| 305 const int32 bitstream_buffer_id = it->second; | 336 const int32 bitstream_buffer_id = it->second; |
| 306 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(), | 337 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(), |
| 307 ++it); | 338 ++it); |
| 308 SendCurrentSurfaceToClient(buf_index, bitstream_buffer_id); | 339 SendCurrentSurfaceToClient(buf_index, bitstream_buffer_id); |
| 309 | 340 |
| 310 // If we decoded a frame this time, then try for another. | 341 // If we decoded a frame this time, then try for another. |
| 311 should_try_again = true; | 342 should_try_again = true; |
| 312 | 343 |
| 313 // Removes ids former or equal than the id from decoder. Note that | 344 // Removes ids former or equal than the id from decoder. Note that |
| 314 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder | 345 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 // software fallback for H264 on Android anyway. | 642 // software fallback for H264 on Android anyway. |
| 612 profile.max_resolution.SetSize(3840, 2160); | 643 profile.max_resolution.SetSize(3840, 2160); |
| 613 profiles.push_back(profile); | 644 profiles.push_back(profile); |
| 614 } | 645 } |
| 615 #endif | 646 #endif |
| 616 | 647 |
| 617 return profiles; | 648 return profiles; |
| 618 } | 649 } |
| 619 | 650 |
| 620 } // namespace content | 651 } // namespace content |
| OLD | NEW |