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

Side by Side Diff: content/renderer/media/rtc_video_decoder.cc

Issue 426873004: Pass decoded picture size from VDA to client (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: simplify size checking Created 6 years, 4 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/renderer/media/rtc_video_decoder.h" 5 #include "content/renderer/media/rtc_video_decoder.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/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/message_loop/message_loop_proxy.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 const size_t size; 54 const size_t size;
55 }; 55 };
56 56
57 RTCVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* shm, size_t size) 57 RTCVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* shm, size_t size)
58 : shm(shm), size(size) {} 58 : shm(shm), size(size) {}
59 59
60 RTCVideoDecoder::SHMBuffer::~SHMBuffer() { shm->Close(); } 60 RTCVideoDecoder::SHMBuffer::~SHMBuffer() { shm->Close(); }
61 61
62 RTCVideoDecoder::BufferData::BufferData(int32 bitstream_buffer_id, 62 RTCVideoDecoder::BufferData::BufferData(int32 bitstream_buffer_id,
63 uint32_t timestamp, 63 uint32_t timestamp,
64 int width,
65 int height,
66 size_t size) 64 size_t size)
67 : bitstream_buffer_id(bitstream_buffer_id), 65 : bitstream_buffer_id(bitstream_buffer_id),
68 timestamp(timestamp), 66 timestamp(timestamp),
69 width(width),
70 height(height),
71 size(size) {} 67 size(size) {}
72 68
73 RTCVideoDecoder::BufferData::BufferData() {} 69 RTCVideoDecoder::BufferData::BufferData() {}
74 70
75 RTCVideoDecoder::BufferData::~BufferData() {} 71 RTCVideoDecoder::BufferData::~BufferData() {}
76 72
77 RTCVideoDecoder::RTCVideoDecoder( 73 RTCVideoDecoder::RTCVideoDecoder(
78 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) 74 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories)
79 : factories_(factories), 75 : factories_(factories),
80 decoder_texture_target_(0), 76 decoder_texture_target_(0),
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 DLOG(ERROR) << "Missing or incomplete frames."; 189 DLOG(ERROR) << "Missing or incomplete frames.";
194 // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames. 190 // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames.
195 // Return an error to request a key frame. 191 // Return an error to request a key frame.
196 return WEBRTC_VIDEO_CODEC_ERROR; 192 return WEBRTC_VIDEO_CODEC_ERROR;
197 } 193 }
198 194
199 // Most platforms' VDA implementations support mid-stream resolution change 195 // Most platforms' VDA implementations support mid-stream resolution change
200 // internally. Platforms whose VDAs fail to support mid-stream resolution 196 // internally. Platforms whose VDAs fail to support mid-stream resolution
201 // change gracefully need to have their clients cover for them, and we do that 197 // change gracefully need to have their clients cover for them, and we do that
202 // here. 198 // here.
199 // Note this may not work because encoded size is not always available.
203 #ifdef ANDROID 200 #ifdef ANDROID
204 const bool kVDACanHandleMidstreamResize = false; 201 const bool kVDACanHandleMidstreamResize = false;
205 #else 202 #else
206 const bool kVDACanHandleMidstreamResize = true; 203 const bool kVDACanHandleMidstreamResize = true;
207 #endif 204 #endif
208 205
209 bool need_to_reset_for_midstream_resize = false; 206 bool need_to_reset_for_midstream_resize = false;
210 if (inputImage._frameType == webrtc::kKeyFrame) { 207 if (inputImage._frameType == webrtc::kKeyFrame) {
211 DVLOG(2) << "Got key frame. size=" << inputImage._encodedWidth << "x" 208 DVLOG(2) << "Got key frame. size=" << inputImage._encodedWidth << "x"
212 << inputImage._encodedHeight; 209 << inputImage._encodedHeight;
213 gfx::Size prev_frame_size = frame_size_; 210 gfx::Size prev_frame_size = frame_size_;
214 frame_size_.SetSize(inputImage._encodedWidth, inputImage._encodedHeight); 211 frame_size_.SetSize(inputImage._encodedWidth, inputImage._encodedHeight);
215 if (!kVDACanHandleMidstreamResize && !prev_frame_size.IsEmpty() && 212 if (!kVDACanHandleMidstreamResize && !prev_frame_size.IsEmpty() &&
216 prev_frame_size != frame_size_) { 213 prev_frame_size != frame_size_) {
217 need_to_reset_for_midstream_resize = true; 214 need_to_reset_for_midstream_resize = true;
218 } 215 }
219 } else if (IsFirstBufferAfterReset(next_bitstream_buffer_id_, 216 } else if (IsFirstBufferAfterReset(next_bitstream_buffer_id_,
220 reset_bitstream_buffer_id_)) { 217 reset_bitstream_buffer_id_)) {
221 // TODO(wuchengli): VDA should handle it. Remove this when 218 // TODO(wuchengli): VDA should handle it. Remove this when
222 // http://crosbug.com/p/21913 is fixed. 219 // http://crosbug.com/p/21913 is fixed.
223 DVLOG(1) << "The first frame should be a key frame. Drop this."; 220 DVLOG(1) << "The first frame should be a key frame. Drop this.";
224 return WEBRTC_VIDEO_CODEC_ERROR; 221 return WEBRTC_VIDEO_CODEC_ERROR;
225 } 222 }
226 223
227 // Create buffer metadata. 224 // Create buffer metadata.
228 BufferData buffer_data(next_bitstream_buffer_id_, 225 BufferData buffer_data(next_bitstream_buffer_id_,
229 inputImage._timeStamp, 226 inputImage._timeStamp,
230 frame_size_.width(),
231 frame_size_.height(),
232 inputImage._length); 227 inputImage._length);
233 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. 228 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
234 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST; 229 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST;
235 230
236 // If a shared memory segment is available, there are no pending buffers, and 231 // If a shared memory segment is available, there are no pending buffers, and
237 // this isn't a mid-stream resolution change, then send the buffer for decode 232 // this isn't a mid-stream resolution change, then send the buffer for decode
238 // immediately. Otherwise, save the buffer in the queue for later decode. 233 // immediately. Otherwise, save the buffer in the queue for later decode.
239 scoped_ptr<SHMBuffer> shm_buffer; 234 scoped_ptr<SHMBuffer> shm_buffer;
240 if (!need_to_reset_for_midstream_resize && pending_buffers_.size() == 0) 235 if (!need_to_reset_for_midstream_resize && pending_buffers_.size() == 0)
241 shm_buffer = GetSHM_Locked(inputImage._length); 236 shm_buffer = GetSHM_Locked(inputImage._length);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 352
358 std::map<int32, media::PictureBuffer>::iterator it = 353 std::map<int32, media::PictureBuffer>::iterator it =
359 assigned_picture_buffers_.find(picture.picture_buffer_id()); 354 assigned_picture_buffers_.find(picture.picture_buffer_id());
360 if (it == assigned_picture_buffers_.end()) { 355 if (it == assigned_picture_buffers_.end()) {
361 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); 356 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id();
362 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 357 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
363 return; 358 return;
364 } 359 }
365 const media::PictureBuffer& pb = it->second; 360 const media::PictureBuffer& pb = it->second;
366 361
362 // Validate picture size from GPU
363 if (picture.size().IsEmpty() ||
364 !gfx::Rect(pb.size()).Contains(gfx::Rect(picture.size()))) {
365 LOG(ERROR) << "Invalid picture size: " << pb.size().ToString()
366 << " from PictureBuffer, but " << picture.size().ToString()
367 << " from GPU";
Pawel Osciak 2014/08/18 07:59:03 Perhaps: "Invalid picture size from VDA: " << pb.
kcwu 2014/08/18 08:07:18 Done. But you exchanged two sizes?
Pawel Osciak 2014/08/18 08:12:23 Ah yes, sorry. Should be the other way around.
368 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
369 return;
370 }
371
367 // Create a media::VideoFrame. 372 // Create a media::VideoFrame.
368 uint32_t timestamp = 0, width = 0, height = 0; 373 uint32_t timestamp = 0;
369 size_t size = 0; 374 GetBufferData(picture.bitstream_buffer_id(), &timestamp);
370 GetBufferData(
371 picture.bitstream_buffer_id(), &timestamp, &width, &height, &size);
372 scoped_refptr<media::VideoFrame> frame = 375 scoped_refptr<media::VideoFrame> frame =
373 CreateVideoFrame(picture, pb, timestamp, width, height, size); 376 CreateVideoFrame(picture, pb, timestamp);
374 bool inserted = 377 bool inserted =
375 picture_buffers_at_display_.insert(std::make_pair( 378 picture_buffers_at_display_.insert(std::make_pair(
376 picture.picture_buffer_id(), 379 picture.picture_buffer_id(),
377 pb.texture_id())).second; 380 pb.texture_id())).second;
378 DCHECK(inserted); 381 DCHECK(inserted);
379 382
380 // Create a WebRTC video frame. 383 // Create a WebRTC video frame.
381 webrtc::RefCountImpl<NativeHandleImpl>* handle = 384 webrtc::RefCountImpl<NativeHandleImpl>* handle =
382 new webrtc::RefCountImpl<NativeHandleImpl>(frame); 385 new webrtc::RefCountImpl<NativeHandleImpl>(frame);
383 webrtc::TextureVideoFrame decoded_image(handle, width, height, timestamp, 0); 386 webrtc::TextureVideoFrame decoded_image(
387 handle, picture.size().width(), picture.size().height(), timestamp, 0);
384 388
385 // Invoke decode callback. WebRTC expects no callback after Reset or Release. 389 // Invoke decode callback. WebRTC expects no callback after Reset or Release.
386 { 390 {
387 base::AutoLock auto_lock(lock_); 391 base::AutoLock auto_lock(lock_);
388 DCHECK(decode_complete_callback_ != NULL); 392 DCHECK(decode_complete_callback_ != NULL);
389 if (IsBufferAfterReset(picture.bitstream_buffer_id(), 393 if (IsBufferAfterReset(picture.bitstream_buffer_id(),
390 reset_bitstream_buffer_id_)) { 394 reset_bitstream_buffer_id_)) {
391 decode_complete_callback_->Decoded(decoded_image); 395 decode_complete_callback_->Decoded(decoded_image);
392 } 396 }
393 } 397 }
(...skipping 22 matching lines...) Expand all
416 visible_rect, 420 visible_rect,
417 pixels, 421 pixels,
418 &event))) 422 &event)))
419 return; 423 return;
420 event.Wait(); 424 event.Wait();
421 } 425 }
422 426
423 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( 427 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
424 const media::Picture& picture, 428 const media::Picture& picture,
425 const media::PictureBuffer& pb, 429 const media::PictureBuffer& pb,
426 uint32_t timestamp, 430 uint32_t timestamp) {
427 uint32_t width, 431 gfx::Rect visible_rect(picture.size());
428 uint32_t height,
429 size_t size) {
430 gfx::Rect visible_rect(width, height);
431 DCHECK(decoder_texture_target_); 432 DCHECK(decoder_texture_target_);
432 // Convert timestamp from 90KHz to ms. 433 // Convert timestamp from 90KHz to ms.
433 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( 434 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue(
434 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); 435 base::checked_cast<uint64_t>(timestamp) * 1000 / 90);
435 return media::VideoFrame::WrapNativeTexture( 436 return media::VideoFrame::WrapNativeTexture(
436 make_scoped_ptr(new gpu::MailboxHolder( 437 make_scoped_ptr(new gpu::MailboxHolder(
437 pb.texture_mailbox(), decoder_texture_target_, 0)), 438 pb.texture_mailbox(), decoder_texture_target_, 0)),
438 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReleaseMailbox, 439 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReleaseMailbox,
439 weak_factory_.GetWeakPtr(), 440 weak_factory_.GetWeakPtr(),
440 factories_, 441 factories_,
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 // that's too small for some pathological B-frame test videos. The cost of 771 // that's too small for some pathological B-frame test videos. The cost of
771 // using too-high a value is low (192 bits per extra slot). 772 // using too-high a value is low (192 bits per extra slot).
772 static const size_t kMaxInputBufferDataSize = 128; 773 static const size_t kMaxInputBufferDataSize = 128;
773 // Pop from the back of the list, because that's the oldest and least likely 774 // Pop from the back of the list, because that's the oldest and least likely
774 // to be useful in the future data. 775 // to be useful in the future data.
775 if (input_buffer_data_.size() > kMaxInputBufferDataSize) 776 if (input_buffer_data_.size() > kMaxInputBufferDataSize)
776 input_buffer_data_.pop_back(); 777 input_buffer_data_.pop_back();
777 } 778 }
778 779
779 void RTCVideoDecoder::GetBufferData(int32 bitstream_buffer_id, 780 void RTCVideoDecoder::GetBufferData(int32 bitstream_buffer_id,
780 uint32_t* timestamp, 781 uint32_t* timestamp) {
781 uint32_t* width,
782 uint32_t* height,
783 size_t* size) {
784 for (std::list<BufferData>::iterator it = input_buffer_data_.begin(); 782 for (std::list<BufferData>::iterator it = input_buffer_data_.begin();
785 it != input_buffer_data_.end(); 783 it != input_buffer_data_.end();
786 ++it) { 784 ++it) {
787 if (it->bitstream_buffer_id != bitstream_buffer_id) 785 if (it->bitstream_buffer_id != bitstream_buffer_id)
788 continue; 786 continue;
789 *timestamp = it->timestamp; 787 *timestamp = it->timestamp;
790 *width = it->width;
791 *height = it->height;
792 return; 788 return;
793 } 789 }
794 NOTREACHED() << "Missing bitstream buffer id: " << bitstream_buffer_id; 790 NOTREACHED() << "Missing bitstream buffer id: " << bitstream_buffer_id;
795 } 791 }
796 792
797 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { 793 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) {
798 // Logging boolean is enough to know if HW decoding has been used. Also, 794 // Logging boolean is enough to know if HW decoding has been used. Also,
799 // InitDecode is less likely to return an error so enum is not used here. 795 // InitDecode is less likely to return an error so enum is not used here.
800 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; 796 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false;
801 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); 797 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample);
802 return status; 798 return status;
803 } 799 }
804 800
805 void RTCVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() 801 void RTCVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
806 const { 802 const {
807 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); 803 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
808 } 804 }
809 805
810 } // namespace content 806 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/rtc_video_decoder.h ('k') | content/renderer/pepper/video_decoder_shim.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698