// Copyright (c) 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ppapi/cpp/video_decoder.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppb_video_decoder.h" #include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/instance_handle.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/module_impl.h" namespace pp { namespace { template <> const char* interface_name() { return PPB_VIDEODECODER_INTERFACE_0_1; } template <> const char* interface_name() { return PPB_VIDEODECODER_INTERFACE_0_2; } template <> const char* interface_name() { return PPB_VIDEODECODER_INTERFACE_1_0; } // This struct is used to adapt CompletionCallbackWithOutput to // the pre-1.0 APIs, which return PP_VideoPicture_0_1. This struct is allocated // on the heap, and deleted in CallbackConverter. struct CallbackData_0_1 { explicit CallbackData_0_1( const CompletionCallbackWithOutput& cc) : original_picture(cc.output()), original_callback(cc.pp_completion_callback()) {} PP_VideoPicture_0_1 picture; PP_VideoPicture* original_picture; PP_CompletionCallback original_callback; }; // Convert a 1.0 style callback to pre-1.0 callback. void CallbackConverter(void* user_data, int32_t result) { CallbackData_0_1* data = static_cast(user_data); if (result == PP_OK) { PP_VideoPicture_0_1* picture = &data->picture; PP_VideoPicture* original_picture = data->original_picture; original_picture->decode_id = picture->decode_id; original_picture->texture_id = picture->texture_id; original_picture->texture_target = picture->texture_target; original_picture->texture_size = picture->texture_size; // Set visible_rect to the entire picture. original_picture->visible_rect = PP_MakeRectFromXYWH( 0, 0, picture->texture_size.width, picture->texture_size.height); } // Now execute the original callback. PP_RunCompletionCallback(&data->original_callback, result); delete data; } } // namespace VideoDecoder::VideoDecoder() { } VideoDecoder::VideoDecoder(const InstanceHandle& instance) { if (has_interface()) { PassRefFromConstructor( get_interface()->Create(instance.pp_instance())); } else if (has_interface()) { PassRefFromConstructor( get_interface()->Create(instance.pp_instance())); } else if (has_interface()) { PassRefFromConstructor( get_interface()->Create(instance.pp_instance())); } } VideoDecoder::VideoDecoder(const VideoDecoder& other) : Resource(other) { } int32_t VideoDecoder::Initialize(const Graphics3D& context, PP_VideoProfile profile, PP_HardwareAcceleration acceleration, const CompletionCallback& cc) { if (has_interface()) { return get_interface()->Initialize( pp_resource(), context.pp_resource(), profile, acceleration, cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Initialize( pp_resource(), context.pp_resource(), profile, acceleration, cc.pp_completion_callback()); } if (has_interface()) { if (acceleration == PP_HARDWAREACCELERATION_NONE) return cc.MayForce(PP_ERROR_NOTSUPPORTED); return get_interface()->Initialize( pp_resource(), context.pp_resource(), profile, acceleration == PP_HARDWAREACCELERATION_WITHFALLBACK ? PP_TRUE : PP_FALSE, cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoDecoder::Decode(uint32_t decode_id, uint32_t size, const void* buffer, const CompletionCallback& cc) { if (has_interface()) { return get_interface()->Decode( pp_resource(), decode_id, size, buffer, cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Decode( pp_resource(), decode_id, size, buffer, cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Decode( pp_resource(), decode_id, size, buffer, cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoDecoder::GetPicture( const CompletionCallbackWithOutput& cc) { if (has_interface()) { return get_interface()->GetPicture( pp_resource(), cc.output(), cc.pp_completion_callback()); } if (has_interface()) { // Data for our callback wrapper. The callback handler will delete it. CallbackData_0_1* data = new CallbackData_0_1(cc); return get_interface()->GetPicture( pp_resource(), &data->picture, PP_MakeCompletionCallback(&CallbackConverter, data)); } if (has_interface()) { // Data for our callback wrapper. The callback handler will delete it. CallbackData_0_1* data = new CallbackData_0_1(cc); return get_interface()->GetPicture( pp_resource(), &data->picture, PP_MakeCompletionCallback(&CallbackConverter, data)); } return cc.MayForce(PP_ERROR_NOINTERFACE); } void VideoDecoder::RecyclePicture(const PP_VideoPicture& picture) { if (has_interface()) { get_interface()->RecyclePicture(pp_resource(), &picture); } else if (has_interface()) { get_interface()->RecyclePicture(pp_resource(), &picture); } else if (has_interface()) { get_interface()->RecyclePicture(pp_resource(), &picture); } } int32_t VideoDecoder::Flush(const CompletionCallback& cc) { if (has_interface()) { return get_interface()->Flush( pp_resource(), cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Flush( pp_resource(), cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Flush( pp_resource(), cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoDecoder::Reset(const CompletionCallback& cc) { if (has_interface()) { return get_interface()->Reset( pp_resource(), cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Reset( pp_resource(), cc.pp_completion_callback()); } if (has_interface()) { return get_interface()->Reset( pp_resource(), cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } } // namespace pp