// Copyright 2015 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_encoder.h" #include #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppb_video_encoder.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_VIDEOENCODER_INTERFACE_0_1; } template <> const char* interface_name() { return PPB_VIDEOENCODER_INTERFACE_0_2; } // This struct is used to adapt // CompletionCallbackWithOutput> // to the pre-0.2 APIs, which return PP_VideoProfileDescription_0_1. // This struct is allocated on the heap, and deleted in // CallbackProfileDescriptionConverter. struct CallbackProfileDescription_0_1 { explicit CallbackProfileDescription_0_1(const CompletionCallbackWithOutput< std::vector >& cc) : output_profiles(&profiles), original_output_profiles(cc.output()), original_callback(cc.pp_completion_callback()) {} std::vector profiles; ArrayOutputAdapter output_profiles; PP_ArrayOutput original_output_profiles; PP_CompletionCallback original_callback; }; // Converts data from a 0.1 style callback to 0.2 callback. void CallbackProfileDescriptionConverter(void* user_data, int32_t result) { CallbackProfileDescription_0_1* data = static_cast(user_data); if (result >= 0) { PP_VideoProfileDescription* original_profiles = static_cast( data->original_output_profiles.GetDataBuffer( data->original_output_profiles.user_data, static_cast(data->profiles.size()), static_cast(sizeof(PP_VideoProfileDescription)))); for (size_t i = 0; i < data->profiles.size(); i++) { const PP_VideoProfileDescription_0_1& profile = data->profiles[i]; original_profiles[i].profile = profile.profile; original_profiles[i].max_resolution = profile.max_resolution; original_profiles[i].max_framerate_numerator = profile.max_framerate_numerator; original_profiles[i].max_framerate_denominator = profile.max_framerate_denominator; original_profiles[i].hardware_accelerated = PP_FromBool(profile.acceleration == PP_HARDWAREACCELERATION_ONLY); } } // Now execute the original callback. PP_RunCompletionCallback(&data->original_callback, result); delete data; } } // namespace VideoEncoder::VideoEncoder() { } VideoEncoder::VideoEncoder(const InstanceHandle& instance) { if (has_interface()) { PassRefFromConstructor( get_interface()->Create(instance.pp_instance())); } else if (has_interface()) { PassRefFromConstructor( get_interface()->Create(instance.pp_instance())); } } VideoEncoder::VideoEncoder(const VideoEncoder& other) : Resource(other) { } int32_t VideoEncoder::GetSupportedProfiles(const CompletionCallbackWithOutput< std::vector >& cc) { if (has_interface()) { return get_interface()->GetSupportedProfiles( pp_resource(), cc.output(), cc.pp_completion_callback()); } else if (has_interface()) { // Data for our callback wrapper. The callback handler will delete it. CallbackProfileDescription_0_1* data = new CallbackProfileDescription_0_1(cc); return get_interface()->GetSupportedProfiles( pp_resource(), data->output_profiles.pp_array_output(), PP_MakeCompletionCallback(&CallbackProfileDescriptionConverter, data)); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoEncoder::Initialize(const PP_VideoFrame_Format& input_format, const Size& input_visible_size, const PP_VideoProfile& output_profile, const uint32_t initial_bitrate, PP_HardwareAcceleration acceleration, const CompletionCallback& cc) { if (has_interface()) { return get_interface()->Initialize( pp_resource(), input_format, &input_visible_size.pp_size(), output_profile, initial_bitrate, acceleration, cc.pp_completion_callback()); } else if (has_interface()) { return get_interface()->Initialize( pp_resource(), input_format, &input_visible_size.pp_size(), output_profile, initial_bitrate, acceleration, cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoEncoder::GetFramesRequired() { if (has_interface()) { return get_interface()->GetFramesRequired( pp_resource()); } else if (has_interface()) { return get_interface()->GetFramesRequired( pp_resource()); } return PP_ERROR_NOINTERFACE; } int32_t VideoEncoder::GetFrameCodedSize(Size* coded_size) { if (has_interface()) { return get_interface()->GetFrameCodedSize( pp_resource(), &coded_size->pp_size()); } else if (has_interface()) { return get_interface()->GetFrameCodedSize( pp_resource(), &coded_size->pp_size()); } return PP_ERROR_NOINTERFACE; } int32_t VideoEncoder::GetVideoFrame( const CompletionCallbackWithOutput& cc) { if (has_interface()) { return get_interface()->GetVideoFrame( pp_resource(), cc.output(), cc.pp_completion_callback()); } else if (has_interface()) { return get_interface()->GetVideoFrame( pp_resource(), cc.output(), cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoEncoder::Encode(const VideoFrame& video_frame, bool force_keyframe, const CompletionCallback& cc) { if (has_interface()) { return get_interface()->Encode( pp_resource(), video_frame.pp_resource(), PP_FromBool(force_keyframe), cc.pp_completion_callback()); } else if (has_interface()) { return get_interface()->Encode( pp_resource(), video_frame.pp_resource(), PP_FromBool(force_keyframe), cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t VideoEncoder::GetBitstreamBuffer( const CompletionCallbackWithOutput& cc) { if (has_interface()) { return get_interface()->GetBitstreamBuffer( pp_resource(), cc.output(), cc.pp_completion_callback()); } else if (has_interface()) { return get_interface()->GetBitstreamBuffer( pp_resource(), cc.output(), cc.pp_completion_callback()); } return cc.MayForce(PP_ERROR_NOINTERFACE); } void VideoEncoder::RecycleBitstreamBuffer( const PP_BitstreamBuffer& bitstream_buffer) { if (has_interface()) { get_interface()->RecycleBitstreamBuffer( pp_resource(), &bitstream_buffer); } else if (has_interface()) { get_interface()->RecycleBitstreamBuffer( pp_resource(), &bitstream_buffer); } } void VideoEncoder::RequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate) { if (has_interface()) { get_interface()->RequestEncodingParametersChange( pp_resource(), bitrate, framerate); } else if (has_interface()) { get_interface()->RequestEncodingParametersChange( pp_resource(), bitrate, framerate); } } void VideoEncoder::Close() { if (has_interface()) { get_interface()->Close(pp_resource()); } else if (has_interface()) { get_interface()->Close(pp_resource()); } } } // namespace pp