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

Side by Side Diff: content/common/gpu/media/vt_video_decode_accelerator.cc

Issue 1320893004: Mac Overlays: Enable h264 overlays (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporate review feedback Created 5 years, 3 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
« no previous file with comments | « content/common/gpu/media/vt_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <algorithm> 5 #include <algorithm>
6 6
7 #include <CoreVideo/CoreVideo.h> 7 #include <CoreVideo/CoreVideo.h>
8 #include <OpenGL/CGLIOSurface.h> 8 #include <OpenGL/CGLIOSurface.h>
9 #include <OpenGL/gl.h> 9 #include <OpenGL/gl.h>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/mac/mac_logging.h" 14 #include "base/mac/mac_logging.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/sys_byteorder.h" 16 #include "base/sys_byteorder.h"
17 #include "base/sys_info.h" 17 #include "base/sys_info.h"
18 #include "base/thread_task_runner_handle.h" 18 #include "base/thread_task_runner_handle.h"
19 #include "base/version.h" 19 #include "base/version.h"
20 #include "content/common/gpu/media/vt_video_decode_accelerator.h" 20 #include "content/common/gpu/media/vt_video_decode_accelerator.h"
21 #include "content/public/common/content_switches.h" 21 #include "content/public/common/content_switches.h"
22 #include "media/base/limits.h" 22 #include "media/base/limits.h"
23 #include "ui/gl/gl_context.h" 23 #include "ui/gl/gl_context.h"
24 #include "ui/gl/gl_image_io_surface.h"
24 #include "ui/gl/scoped_binders.h" 25 #include "ui/gl/scoped_binders.h"
25 26
26 using content_common_gpu_media::kModuleVt; 27 using content_common_gpu_media::kModuleVt;
27 using content_common_gpu_media::InitializeStubs; 28 using content_common_gpu_media::InitializeStubs;
28 using content_common_gpu_media::IsVtInitialized; 29 using content_common_gpu_media::IsVtInitialized;
29 using content_common_gpu_media::StubPathMap; 30 using content_common_gpu_media::StubPathMap;
30 31
31 #define NOTIFY_STATUS(name, status, session_failure) \ 32 #define NOTIFY_STATUS(name, status, session_failure) \
32 do { \ 33 do { \
33 OSSTATUS_DLOG(ERROR, status) << name; \ 34 OSSTATUS_DLOG(ERROR, status) << name; \
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 VTVideoDecodeAccelerator::Task::~Task() { 268 VTVideoDecodeAccelerator::Task::~Task() {
268 } 269 }
269 270
270 VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id) 271 VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id)
271 : bitstream_id(bitstream_id), pic_order_cnt(0), reorder_window(0) { 272 : bitstream_id(bitstream_id), pic_order_cnt(0), reorder_window(0) {
272 } 273 }
273 274
274 VTVideoDecodeAccelerator::Frame::~Frame() { 275 VTVideoDecodeAccelerator::Frame::~Frame() {
275 } 276 }
276 277
278 VTVideoDecodeAccelerator::PictureInfo::PictureInfo(uint32_t client_texture_id,
279 uint32_t service_texture_id)
280 : client_texture_id(client_texture_id),
281 service_texture_id(service_texture_id) {}
282
283 VTVideoDecodeAccelerator::PictureInfo::~PictureInfo() {
284 if (gl_image)
285 gl_image->Destroy(false);
286 }
287
277 bool VTVideoDecodeAccelerator::FrameOrder::operator()( 288 bool VTVideoDecodeAccelerator::FrameOrder::operator()(
278 const linked_ptr<Frame>& lhs, 289 const linked_ptr<Frame>& lhs,
279 const linked_ptr<Frame>& rhs) const { 290 const linked_ptr<Frame>& rhs) const {
280 if (lhs->pic_order_cnt != rhs->pic_order_cnt) 291 if (lhs->pic_order_cnt != rhs->pic_order_cnt)
281 return lhs->pic_order_cnt > rhs->pic_order_cnt; 292 return lhs->pic_order_cnt > rhs->pic_order_cnt;
282 // If |pic_order_cnt| is the same, fall back on using the bitstream order. 293 // If |pic_order_cnt| is the same, fall back on using the bitstream order.
283 // TODO(sandersd): Assign a sequence number in Decode() and use that instead. 294 // TODO(sandersd): Assign a sequence number in Decode() and use that instead.
284 // TODO(sandersd): Using the sequence number, ensure that frames older than 295 // TODO(sandersd): Using the sequence number, ensure that frames older than
285 // |kMaxReorderQueueSize| are ordered first, regardless of |pic_order_cnt|. 296 // |kMaxReorderQueueSize| are ordered first, regardless of |pic_order_cnt|.
286 return lhs->bitstream_id > rhs->bitstream_id; 297 return lhs->bitstream_id > rhs->bitstream_id;
287 } 298 }
288 299
289 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator( 300 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
290 const base::Callback<bool(void)>& make_context_current) 301 const base::Callback<bool(void)>& make_context_current,
302 const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>&
303 bind_image)
291 : make_context_current_(make_context_current), 304 : make_context_current_(make_context_current),
305 bind_image_(bind_image),
292 client_(nullptr), 306 client_(nullptr),
293 state_(STATE_DECODING), 307 state_(STATE_DECODING),
294 format_(nullptr), 308 format_(nullptr),
295 session_(nullptr), 309 session_(nullptr),
296 last_sps_id_(-1), 310 last_sps_id_(-1),
297 last_pps_id_(-1), 311 last_pps_id_(-1),
298 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()), 312 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
299 decoder_thread_("VTDecoderThread"), 313 decoder_thread_("VTDecoderThread"),
300 weak_this_factory_(this) { 314 weak_this_factory_(this) {
301 DCHECK(!make_context_current_.is_null()); 315 DCHECK(!make_context_current_.is_null());
302 callback_.decompressionOutputCallback = OutputThunk; 316 callback_.decompressionOutputCallback = OutputThunk;
303 callback_.decompressionOutputRefCon = this; 317 callback_.decompressionOutputRefCon = this;
304 weak_this_ = weak_this_factory_.GetWeakPtr(); 318 weak_this_ = weak_this_factory_.GetWeakPtr();
305 } 319 }
306 320
307 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { 321 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() {
322 DCHECK(gpu_thread_checker_.CalledOnValidThread());
308 } 323 }
309 324
310 bool VTVideoDecodeAccelerator::Initialize( 325 bool VTVideoDecodeAccelerator::Initialize(
311 media::VideoCodecProfile profile, 326 media::VideoCodecProfile profile,
312 Client* client) { 327 Client* client) {
313 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 328 DCHECK(gpu_thread_checker_.CalledOnValidThread());
314 client_ = client; 329 client_ = client;
315 330
316 if (!InitializeVideoToolbox()) 331 if (!InitializeVideoToolbox())
317 return false; 332 return false;
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 decoder_thread_.task_runner()->PostTask( 818 decoder_thread_.task_runner()->PostTask(
804 FROM_HERE, base::Bind(&VTVideoDecodeAccelerator::DecodeTask, 819 FROM_HERE, base::Bind(&VTVideoDecodeAccelerator::DecodeTask,
805 base::Unretained(this), bitstream, frame)); 820 base::Unretained(this), bitstream, frame));
806 } 821 }
807 822
808 void VTVideoDecodeAccelerator::AssignPictureBuffers( 823 void VTVideoDecodeAccelerator::AssignPictureBuffers(
809 const std::vector<media::PictureBuffer>& pictures) { 824 const std::vector<media::PictureBuffer>& pictures) {
810 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 825 DCHECK(gpu_thread_checker_.CalledOnValidThread());
811 826
812 for (const media::PictureBuffer& picture : pictures) { 827 for (const media::PictureBuffer& picture : pictures) {
813 DCHECK(!texture_ids_.count(picture.id())); 828 DCHECK(!picture_info_map_.count(picture.id()));
814 assigned_picture_ids_.insert(picture.id()); 829 assigned_picture_ids_.insert(picture.id());
815 available_picture_ids_.push_back(picture.id()); 830 available_picture_ids_.push_back(picture.id());
816 texture_ids_[picture.id()] = picture.texture_id(); 831 picture_info_map_.insert(picture.id(), make_scoped_ptr(new PictureInfo(
832 picture.internal_texture_id(),
833 picture.texture_id())));
817 } 834 }
818 835
819 // Pictures are not marked as uncleared until after this method returns, and 836 // Pictures are not marked as uncleared until after this method returns, and
820 // they will be broken if they are used before that happens. So, schedule 837 // they will be broken if they are used before that happens. So, schedule
821 // future work after that happens. 838 // future work after that happens.
822 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 839 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
823 &VTVideoDecodeAccelerator::ProcessWorkQueues, weak_this_)); 840 &VTVideoDecodeAccelerator::ProcessWorkQueues, weak_this_));
824 } 841 }
825 842
826 void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) { 843 void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
827 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 844 DCHECK(gpu_thread_checker_.CalledOnValidThread());
828 DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1); 845 DCHECK(picture_info_map_.count(picture_id));
829 picture_bindings_.erase(picture_id); 846 PictureInfo* picture_info = picture_info_map_.find(picture_id)->second;
847 DCHECK_EQ(CFGetRetainCount(picture_info->cv_image), 1);
848 picture_info->cv_image.reset();
849 picture_info->gl_image->Destroy(false);
850 picture_info->gl_image = nullptr;
851
830 if (assigned_picture_ids_.count(picture_id) != 0) { 852 if (assigned_picture_ids_.count(picture_id) != 0) {
831 available_picture_ids_.push_back(picture_id); 853 available_picture_ids_.push_back(picture_id);
832 ProcessWorkQueues(); 854 ProcessWorkQueues();
833 } else { 855 } else {
834 client_->DismissPictureBuffer(picture_id); 856 client_->DismissPictureBuffer(picture_id);
835 } 857 }
836 } 858 }
837 859
838 void VTVideoDecodeAccelerator::ProcessWorkQueues() { 860 void VTVideoDecodeAccelerator::ProcessWorkQueues() {
839 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 861 DCHECK(gpu_thread_checker_.CalledOnValidThread());
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 } 1000 }
979 1001
980 bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { 1002 bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
981 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 1003 DCHECK(gpu_thread_checker_.CalledOnValidThread());
982 DCHECK_EQ(state_, STATE_DECODING); 1004 DCHECK_EQ(state_, STATE_DECODING);
983 1005
984 if (available_picture_ids_.empty()) 1006 if (available_picture_ids_.empty())
985 return false; 1007 return false;
986 1008
987 int32_t picture_id = available_picture_ids_.back(); 1009 int32_t picture_id = available_picture_ids_.back();
988 IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image.get()); 1010 DCHECK(picture_info_map_.count(picture_id));
1011 PictureInfo* picture_info = picture_info_map_.find(picture_id)->second;
1012 DCHECK(!picture_info->cv_image);
1013 DCHECK(!picture_info->gl_image);
989 1014
990 if (!make_context_current_.Run()) { 1015 if (!make_context_current_.Run()) {
991 DLOG(ERROR) << "Failed to make GL context current"; 1016 DLOG(ERROR) << "Failed to make GL context current";
992 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); 1017 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
993 return false; 1018 return false;
994 } 1019 }
995 1020
1021 IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image.get());
996 glEnable(GL_TEXTURE_RECTANGLE_ARB); 1022 glEnable(GL_TEXTURE_RECTANGLE_ARB);
997 gfx::ScopedTextureBinder 1023 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_RECTANGLE_ARB,
998 texture_binder(GL_TEXTURE_RECTANGLE_ARB, texture_ids_[picture_id]); 1024 picture_info->service_texture_id);
999 CGLContextObj cgl_context = 1025 CGLContextObj cgl_context =
1000 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); 1026 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle());
1001 CGLError status = CGLTexImageIOSurface2D( 1027 CGLError status = CGLTexImageIOSurface2D(
1002 cgl_context, // ctx 1028 cgl_context, // ctx
1003 GL_TEXTURE_RECTANGLE_ARB, // target 1029 GL_TEXTURE_RECTANGLE_ARB, // target
1004 GL_RGB, // internal_format 1030 GL_RGB, // internal_format
1005 frame.coded_size.width(), // width 1031 frame.coded_size.width(), // width
1006 frame.coded_size.height(), // height 1032 frame.coded_size.height(), // height
1007 GL_YCBCR_422_APPLE, // format 1033 GL_YCBCR_422_APPLE, // format
1008 GL_UNSIGNED_SHORT_8_8_APPLE, // type 1034 GL_UNSIGNED_SHORT_8_8_APPLE, // type
1009 surface, // io_surface 1035 surface, // io_surface
1010 0); // plane 1036 0); // plane
1011 glDisable(GL_TEXTURE_RECTANGLE_ARB); 1037 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1012 if (status != kCGLNoError) { 1038 if (status != kCGLNoError) {
1013 NOTIFY_STATUS("CGLTexImageIOSurface2D()", status, SFT_PLATFORM_ERROR); 1039 NOTIFY_STATUS("CGLTexImageIOSurface2D()", status, SFT_PLATFORM_ERROR);
1014 return false; 1040 return false;
1015 } 1041 }
1016 1042
1043 bool allow_overlay = false;
1044 scoped_refptr<gfx::GLImageIOSurface> gl_image(new gfx::GLImageIOSurface(
1045 gfx::GenericSharedMemoryId(), frame.coded_size, GL_BGRA_EXT));
1046 if (gl_image->Initialize(surface, gfx::BufferFormat::BGRA_8888)) {
1047 allow_overlay = true;
1048 } else {
1049 gl_image = nullptr;
1050 }
1051 bind_image_.Run(picture_info->client_texture_id, GL_TEXTURE_RECTANGLE_ARB,
1052 gl_image);
1053
1054 // Assign the new image(s) to the the picture info.
1055 picture_info->gl_image = gl_image;
1056 picture_info->cv_image = frame.image;
1017 available_picture_ids_.pop_back(); 1057 available_picture_ids_.pop_back();
1018 picture_bindings_[picture_id] = frame.image; 1058
1019 // TODO(sandersd): Currently, the size got from 1059 // TODO(sandersd): Currently, the size got from
1020 // CMVideoFormatDescriptionGetDimensions is visible size. We pass it to 1060 // CMVideoFormatDescriptionGetDimensions is visible size. We pass it to
1021 // GpuVideoDecoder so that GpuVideoDecoder can use correct visible size in 1061 // GpuVideoDecoder so that GpuVideoDecoder can use correct visible size in
1022 // resolution changed. We should find the correct API to get the real 1062 // resolution changed. We should find the correct API to get the real
1023 // coded size and fix it. 1063 // coded size and fix it.
1024 client_->PictureReady(media::Picture(picture_id, frame.bitstream_id, 1064 client_->PictureReady(media::Picture(picture_id, frame.bitstream_id,
1025 gfx::Rect(frame.coded_size), false)); 1065 gfx::Rect(frame.coded_size),
1066 allow_overlay));
1026 return true; 1067 return true;
1027 } 1068 }
1028 1069
1029 void VTVideoDecodeAccelerator::NotifyError( 1070 void VTVideoDecodeAccelerator::NotifyError(
1030 Error vda_error_type, 1071 Error vda_error_type,
1031 VTVDASessionFailureType session_failure_type) { 1072 VTVDASessionFailureType session_failure_type) {
1032 DCHECK_LT(session_failure_type, SFT_MAX + 1); 1073 DCHECK_LT(session_failure_type, SFT_MAX + 1);
1033 if (!gpu_thread_checker_.CalledOnValidThread()) { 1074 if (!gpu_thread_checker_.CalledOnValidThread()) {
1034 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 1075 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
1035 &VTVideoDecodeAccelerator::NotifyError, weak_this_, vda_error_type, 1076 &VTVideoDecodeAccelerator::NotifyError, weak_this_, vda_error_type,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 SupportedProfile profile; 1138 SupportedProfile profile;
1098 profile.profile = supported_profile; 1139 profile.profile = supported_profile;
1099 profile.min_resolution.SetSize(16, 16); 1140 profile.min_resolution.SetSize(16, 16);
1100 profile.max_resolution.SetSize(4096, 2160); 1141 profile.max_resolution.SetSize(4096, 2160);
1101 profiles.push_back(profile); 1142 profiles.push_back(profile);
1102 } 1143 }
1103 return profiles; 1144 return profiles;
1104 } 1145 }
1105 1146
1106 } // namespace content 1147 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/vt_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698