| OLD | NEW |
| 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 #include <stddef.h> | 10 #include <stddef.h> |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 // Maximum number of frames to queue for reordering before we stop asking for | 67 // Maximum number of frames to queue for reordering before we stop asking for |
| 68 // more. (NotifyEndOfBitstreamBuffer() is called when frames are moved into the | 68 // more. (NotifyEndOfBitstreamBuffer() is called when frames are moved into the |
| 69 // reorder queue.) | 69 // reorder queue.) |
| 70 static const int kMaxReorderQueueSize = 16; | 70 static const int kMaxReorderQueueSize = 16; |
| 71 | 71 |
| 72 // Build an |image_config| dictionary for VideoToolbox initialization. | 72 // Build an |image_config| dictionary for VideoToolbox initialization. |
| 73 static base::ScopedCFTypeRef<CFMutableDictionaryRef> | 73 static base::ScopedCFTypeRef<CFMutableDictionaryRef> |
| 74 BuildImageConfig(CMVideoDimensions coded_dimensions) { | 74 BuildImageConfig(CMVideoDimensions coded_dimensions) { |
| 75 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config; | 75 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config; |
| 76 | 76 |
| 77 // 4:2:2 is used over the native 4:2:0 because only 4:2:2 can be directly | 77 // Note that 4:2:0 textures cannot be used directly as RGBA in OpenGL, but are |
| 78 // bound to a texture by CGLTexImageIOSurface2D(). | 78 // lower power than 4:2:2 when composited directly by CoreAnimation. |
| 79 int32_t pixel_format = kCVPixelFormatType_422YpCbCr8; | 79 int32_t pixel_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; |
| 80 #define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i) | 80 #define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i) |
| 81 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format)); | 81 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format)); |
| 82 base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width)); | 82 base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width)); |
| 83 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height)); | 83 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height)); |
| 84 #undef CFINT | 84 #undef CFINT |
| 85 if (!cf_pixel_format.get() || !cf_width.get() || !cf_height.get()) | 85 if (!cf_pixel_format.get() || !cf_width.get() || !cf_height.get()) |
| 86 return image_config; | 86 return image_config; |
| 87 | 87 |
| 88 image_config.reset( | 88 image_config.reset( |
| 89 CFDictionaryCreateMutable( | 89 CFDictionaryCreateMutable( |
| 90 kCFAllocatorDefault, | 90 kCFAllocatorDefault, |
| 91 4, // capacity | 91 3, // capacity |
| 92 &kCFTypeDictionaryKeyCallBacks, | 92 &kCFTypeDictionaryKeyCallBacks, |
| 93 &kCFTypeDictionaryValueCallBacks)); | 93 &kCFTypeDictionaryValueCallBacks)); |
| 94 if (!image_config.get()) | 94 if (!image_config.get()) |
| 95 return image_config; | 95 return image_config; |
| 96 | 96 |
| 97 CFDictionarySetValue(image_config, kCVPixelBufferPixelFormatTypeKey, | 97 CFDictionarySetValue(image_config, kCVPixelBufferPixelFormatTypeKey, |
| 98 cf_pixel_format); | 98 cf_pixel_format); |
| 99 CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width); | 99 CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width); |
| 100 CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height); | 100 CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height); |
| 101 CFDictionarySetValue(image_config, kCVPixelBufferOpenGLCompatibilityKey, | |
| 102 kCFBooleanTrue); | |
| 103 | 101 |
| 104 return image_config; | 102 return image_config; |
| 105 } | 103 } |
| 106 | 104 |
| 107 // Create a VTDecompressionSession using the provided |pps| and |sps|. If | 105 // Create a VTDecompressionSession using the provided |pps| and |sps|. If |
| 108 // |require_hardware| is true, the session must uses real hardware decoding | 106 // |require_hardware| is true, the session must uses real hardware decoding |
| 109 // (as opposed to software decoding inside of VideoToolbox) to be considered | 107 // (as opposed to software decoding inside of VideoToolbox) to be considered |
| 110 // successful. | 108 // successful. |
| 111 // | 109 // |
| 112 // TODO(sandersd): Merge with ConfigureDecoder(), as the code is very similar. | 110 // TODO(sandersd): Merge with ConfigureDecoder(), as the code is very similar. |
| (...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 DLOG(ERROR) << "Failed to make GL context current"; | 1031 DLOG(ERROR) << "Failed to make GL context current"; |
| 1034 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); | 1032 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); |
| 1035 return false; | 1033 return false; |
| 1036 } | 1034 } |
| 1037 | 1035 |
| 1038 IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(frame.image.get()); | 1036 IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(frame.image.get()); |
| 1039 | 1037 |
| 1040 scoped_refptr<gl::GLImageIOSurface> gl_image( | 1038 scoped_refptr<gl::GLImageIOSurface> gl_image( |
| 1041 new gl::GLImageIOSurface(frame.coded_size, GL_BGRA_EXT)); | 1039 new gl::GLImageIOSurface(frame.coded_size, GL_BGRA_EXT)); |
| 1042 if (!gl_image->Initialize(io_surface, gfx::GenericSharedMemoryId(), | 1040 if (!gl_image->Initialize(io_surface, gfx::GenericSharedMemoryId(), |
| 1043 gfx::BufferFormat::UYVY_422)) { | 1041 gfx::BufferFormat::YUV_420_BIPLANAR)) { |
| 1044 NOTIFY_STATUS("Failed to initialize GLImageIOSurface", PLATFORM_FAILURE, | 1042 NOTIFY_STATUS("Failed to initialize GLImageIOSurface", PLATFORM_FAILURE, |
| 1045 SFT_PLATFORM_ERROR); | 1043 SFT_PLATFORM_ERROR); |
| 1046 } | 1044 } |
| 1047 | 1045 |
| 1048 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGLCoreProfile) | |
| 1049 glEnable(GL_TEXTURE_RECTANGLE_ARB); | |
| 1050 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_RECTANGLE_ARB, | |
| 1051 picture_info->service_texture_id); | |
| 1052 bool bind_result = gl_image->BindTexImage(GL_TEXTURE_RECTANGLE_ARB); | |
| 1053 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGLCoreProfile) | |
| 1054 glDisable(GL_TEXTURE_RECTANGLE_ARB); | |
| 1055 if (!bind_result) { | |
| 1056 NOTIFY_STATUS("Failed BindTexImage on GLImageIOSurface", PLATFORM_FAILURE, | |
| 1057 SFT_PLATFORM_ERROR); | |
| 1058 return false; | |
| 1059 } | |
| 1060 | |
| 1061 bind_image_.Run(picture_info->client_texture_id, GL_TEXTURE_RECTANGLE_ARB, | 1046 bind_image_.Run(picture_info->client_texture_id, GL_TEXTURE_RECTANGLE_ARB, |
| 1062 gl_image, true); | 1047 gl_image, false); |
| 1063 | 1048 |
| 1064 // Assign the new image(s) to the the picture info. | 1049 // Assign the new image(s) to the the picture info. |
| 1065 picture_info->gl_image = gl_image; | 1050 picture_info->gl_image = gl_image; |
| 1066 picture_info->cv_image = frame.image; | 1051 picture_info->cv_image = frame.image; |
| 1067 available_picture_ids_.pop_back(); | 1052 available_picture_ids_.pop_back(); |
| 1068 | 1053 |
| 1069 // TODO(sandersd): Currently, the size got from | 1054 // TODO(sandersd): Currently, the size got from |
| 1070 // CMVideoFormatDescriptionGetDimensions is visible size. We pass it to | 1055 // CMVideoFormatDescriptionGetDimensions is visible size. We pass it to |
| 1071 // GpuVideoDecoder so that GpuVideoDecoder can use correct visible size in | 1056 // GpuVideoDecoder so that GpuVideoDecoder can use correct visible size in |
| 1072 // resolution changed. We should find the correct API to get the real | 1057 // resolution changed. We should find the correct API to get the real |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 SupportedProfile profile; | 1133 SupportedProfile profile; |
| 1149 profile.profile = supported_profile; | 1134 profile.profile = supported_profile; |
| 1150 profile.min_resolution.SetSize(16, 16); | 1135 profile.min_resolution.SetSize(16, 16); |
| 1151 profile.max_resolution.SetSize(4096, 2160); | 1136 profile.max_resolution.SetSize(4096, 2160); |
| 1152 profiles.push_back(profile); | 1137 profiles.push_back(profile); |
| 1153 } | 1138 } |
| 1154 return profiles; | 1139 return profiles; |
| 1155 } | 1140 } |
| 1156 | 1141 |
| 1157 } // namespace content | 1142 } // namespace content |
| OLD | NEW |