diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-25 16:44:44 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-25 16:44:44 +0000 |
commit | 3a94b248df450e40596b57b27a06ffb4a9dc42df (patch) | |
tree | 7359466d2c6d12680731fe4d3f8282cf45bed637 | |
parent | eb68424725a94620e747adcaaf12471b9ae197b3 (diff) | |
download | chromium_src-3a94b248df450e40596b57b27a06ffb4a9dc42df.zip chromium_src-3a94b248df450e40596b57b27a06ffb4a9dc42df.tar.gz chromium_src-3a94b248df450e40596b57b27a06ffb4a9dc42df.tar.bz2 |
Revert 279650 "Add VaapiVideoEncodeAccelerator for HW-accelerate..."
Broke the Chrome-on-Chrome OS compile
http://master.chrome.corp.google.com:8011/builders/cros%20trunk/builds/21417
> Add VaapiVideoEncodeAccelerator for HW-accelerated video encode.
>
> Add an implementation of VideoEncodeAccelerator utilizing VA-API for
> hardware encode on Intel-based ChromeOS platforms.
>
> BUG=378962
> TEST=video_encode_accelerator_unittest
>
> Review URL: https://codereview.chromium.org/333253002
TBR=posciak@chromium.org
Review URL: https://codereview.chromium.org/350413002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279733 0039d316-1c4b-4281-b951-d872f2087c98
26 files changed, 87 insertions, 2185 deletions
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 7492b44..74c93b6 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc @@ -158,7 +158,6 @@ std::string DeriveCommandLine(const GURL& start_url, ::switches::kDisableWebRtcHWEncoding, ::switches::kEnableWebRtcHWVp8Encoding, #endif - ::switches::kEnableVaapiAcceleratedVideoEncode, #if defined(USE_OZONE) ::switches::kOzonePlatform, #endif diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 69d7320..96a233e 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -981,9 +981,6 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { #endif switches::kEnableLogging, switches::kEnableShareGroupAsyncTextureUpload, -#if defined(OS_CHROMEOS) - switches::kEnableVaapiAcceleratedVideoEncode, -#endif switches::kGpuStartupDialog, switches::kGpuSandboxAllowSysVShm, switches::kGpuSandboxFailuresFatal, diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index bca6072..b67ecae 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -1256,9 +1256,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kDisableDirectWrite, switches::kEnableHighResolutionTime, #endif -#if defined(OS_CHROMEOS) - switches::kEnableVaapiAcceleratedVideoEncode, -#endif }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, arraysize(kSwitchNames)); diff --git a/content/common/gpu/media/gpu_video_encode_accelerator.cc b/content/common/gpu/media/gpu_video_encode_accelerator.cc index 52ecab8..12c7b10 100644 --- a/content/common/gpu/media/gpu_video_encode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_encode_accelerator.cc @@ -5,27 +5,18 @@ #include "content/common/gpu/media/gpu_video_encode_accelerator.h" #include "base/callback.h" -#include "base/command_line.h" #include "base/logging.h" #include "base/memory/shared_memory.h" #include "base/message_loop/message_loop_proxy.h" #include "build/build_config.h" #include "content/common/gpu/gpu_channel.h" #include "content/common/gpu/gpu_messages.h" -#include "content/public/common/content_switches.h" #include "ipc/ipc_message_macros.h" #include "media/base/limits.h" #include "media/base/video_frame.h" -#if defined(OS_CHROMEOS) && defined(USE_X11) - -#if defined(ARCH_CPU_ARMEL) +#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" -#elif defined(ARCH_CPU_X86_FAMILY) -#include "content/common/gpu/media/vaapi_video_encode_accelerator.h" -#include "ui/gfx/x/x11_types.h" -#endif - #elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC) #include "content/common/gpu/media/android_video_encode_accelerator.h" #endif @@ -167,12 +158,8 @@ std::vector<media::VideoEncodeAccelerator::SupportedProfile> GpuVideoEncodeAccelerator::GetSupportedProfiles() { std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles; -#if defined(OS_CHROMEOS) && defined(USE_X11) -#if defined(ARCH_CPU_ARMEL) +#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) profiles = V4L2VideoEncodeAccelerator::GetSupportedProfiles(); -#elif defined(ARCH_CPU_X86_FAMILY) - profiles = VaapiVideoEncodeAccelerator::GetSupportedProfiles(); -#endif #elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC) profiles = AndroidVideoEncodeAccelerator::GetSupportedProfiles(); #endif @@ -183,18 +170,12 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles() { void GpuVideoEncodeAccelerator::CreateEncoder() { DCHECK(!encoder_); -#if defined(OS_CHROMEOS) && defined(USE_X11) -#if defined(ARCH_CPU_ARMEL) +#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); if (!device.get()) return; encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass())); -#elif defined(ARCH_CPU_X86_FAMILY) - const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); - if (cmd_line->HasSwitch(switches::kEnableVaapiAcceleratedVideoEncode)) - encoder_.reset(new VaapiVideoEncodeAccelerator(gfx::GetXDisplay())); -#endif #elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC) encoder_.reset(new AndroidVideoEncodeAccelerator()); #endif diff --git a/content/common/gpu/media/h264_dpb.h b/content/common/gpu/media/h264_dpb.h index 366c47a..29be0bc 100644 --- a/content/common/gpu/media/h264_dpb.h +++ b/content/common/gpu/media/h264_dpb.h @@ -41,7 +41,6 @@ struct H264Picture { int frame_num_wrap; int long_term_frame_idx; - media::H264SliceHeader::Type type; bool idr; // IDR picture? bool ref; // reference picture? bool long_term; // long term reference picture? diff --git a/content/common/gpu/media/va.sigs b/content/common/gpu/media/va.sigs index 9906f9f..b3cea38 100644 --- a/content/common/gpu/media/va.sigs +++ b/content/common/gpu/media/va.sigs @@ -22,9 +22,7 @@ const char *vaErrorStr(VAStatus error_status); VAStatus vaGetConfigAttributes(VADisplay dpy, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs); VAStatus vaInitialize(VADisplay dpy, int *major_version, int *minor_version); VAStatus vaMapBuffer(VADisplay dpy, VABufferID buf_id, void **pbuf); -int vaMaxNumEntrypoints (VADisplay dpy); int vaMaxNumProfiles(VADisplay dpy); -VAStatus vaQueryConfigEntrypoints (VADisplay dpy, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints); VAStatus vaQueryConfigProfiles(VADisplay dpy, VAProfile *profile_list, int *num_profiles); VAStatus vaRenderPicture(VADisplay dpy, VAContextID context, VABufferID *buffers, int num_buffers); VAStatus vaSetDisplayAttributes(VADisplay dpy, VADisplayAttribute *attr_list, int num_attributes); diff --git a/content/common/gpu/media/vaapi_h264_decoder.cc b/content/common/gpu/media/vaapi_h264_decoder.cc index 91e76af..9654a3c 100644 --- a/content/common/gpu/media/vaapi_h264_decoder.cc +++ b/content/common/gpu/media/vaapi_h264_decoder.cc @@ -488,8 +488,8 @@ bool VaapiH264Decoder::DecodePicture() { return false; } - if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( - dec_surface->va_surface()->id())) { + if (!vaapi_wrapper_->DecodeAndDestroyPendingBuffers( + dec_surface->va_surface()->id())) { DVLOG(1) << "Failed decoding picture"; return false; } diff --git a/content/common/gpu/media/vaapi_h264_decoder_unittest.cc b/content/common/gpu/media/vaapi_h264_decoder_unittest.cc index b14c50b..6bd873e 100644 --- a/content/common/gpu/media/vaapi_h264_decoder_unittest.cc +++ b/content/common/gpu/media/vaapi_h264_decoder_unittest.cc @@ -127,8 +127,7 @@ bool VaapiH264DecoderLoop::Initialize(base::FilePath input_file, media::VideoCodecProfile profile = media::H264PROFILE_BASELINE; base::Closure report_error_cb = base::Bind(&LogOnError, VaapiH264Decoder::VAAPI_ERROR); - wrapper_ = VaapiWrapper::Create( - VaapiWrapper::kDecode, profile, x_display_, report_error_cb); + wrapper_ = VaapiWrapper::Create(profile, x_display_, report_error_cb); if (!wrapper_.get()) { LOG(ERROR) << "Can't create vaapi wrapper"; return false; diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc index afcfc8a..b68f5d4 100644 --- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc +++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc @@ -300,9 +300,7 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, } vaapi_wrapper_ = VaapiWrapper::Create( - VaapiWrapper::kDecode, - profile, - x_display_, + profile, x_display_, base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR)); if (!vaapi_wrapper_.get()) { diff --git a/content/common/gpu/media/vaapi_video_encode_accelerator.cc b/content/common/gpu/media/vaapi_video_encode_accelerator.cc deleted file mode 100644 index 6cfdd9d..0000000 --- a/content/common/gpu/media/vaapi_video_encode_accelerator.cc +++ /dev/null @@ -1,1061 +0,0 @@ -// Copyright 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 "content/common/gpu/media/vaapi_video_encode_accelerator.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/metrics/histogram.h" -#include "base/numerics/safe_conversions.h" -#include "content/common/gpu/media/h264_dpb.h" -#include "content/public/common/content_switches.h" -#include "media/base/bind_to_current_loop.h" -#include "third_party/libva/va/va_enc_h264.h" - -#define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " - -#define NOTIFY_ERROR(error, msg) \ - do { \ - SetState(kError); \ - DVLOGF(1) << msg; \ - DVLOGF(1) << "Calling NotifyError(" << error << ")"; \ - NotifyError(error); \ - } while (0) - -namespace content { - -namespace { -// Need 2 surfaces for each frame: one for input data and one for -// reconstructed picture, which is later used for reference. -const size_t kMinSurfacesToEncode = 2; - -// Subjectively chosen. -const size_t kNumInputBuffers = 4; -const size_t kMaxNumReferenceFrames = 4; - -// We need up to kMaxNumReferenceFrames surfaces for reference, plus one -// for input and one for encode (which will be added to the set of reference -// frames for subsequent frames). Actual execution of HW encode is done -// in parallel, and we want to process more frames in the meantime. -// To have kNumInputBuffers in flight, we need a full set of reference + -// encode surfaces (i.e. kMaxNumReferenceFrames + kMinSurfacesToEncode), and -// (kNumInputBuffers - 1) of kMinSurfacesToEncode for the remaining frames -// in flight. -const size_t kNumSurfaces = kMaxNumReferenceFrames + kMinSurfacesToEncode + - kMinSurfacesToEncode * (kNumInputBuffers - 1); - -// An IDR every 128 frames, an I frame every 30 and no B frames. -const int kIDRPeriod = 128; -const int kIPeriod = 30; -const int kIPPeriod = 1; - -const int kDefaultFramerate = 30; - -// HRD parameters (ch. E.2.2 in spec). -const int kBitRateScale = 0; // bit_rate_scale for SPS HRD parameters. -const int kCPBSizeScale = 0; // cpb_size_scale for SPS HRD parameters. - -const int kDefaultQP = 26; -// All Intel codecs can do at least 4.1. -const int kDefaultLevelIDC = 41; -const int kChromaFormatIDC = 1; // 4:2:0 - -// Arbitrarily chosen bitrate window size for rate control, in ms. -const int kCPBWindowSizeMs = 1500; - -// UMA errors that the VaapiVideoEncodeAccelerator class reports. -enum VAVEAEncoderFailure { - VAAPI_ERROR = 0, - VAVEA_ENCODER_FAILURES_MAX, -}; - -} - -// Round |value| up to |alignment|, which must be a power of 2. -static inline size_t RoundUpToPowerOf2(size_t value, size_t alignment) { - // Check that |alignment| is a power of 2. - DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); - return ((value + (alignment - 1)) & ~(alignment - 1)); -} - -static void ReportToUMA(VAVEAEncoderFailure failure) { - UMA_HISTOGRAM_ENUMERATION( - "Media.VAVEA.EncoderFailure", - failure, - VAVEA_ENCODER_FAILURES_MAX); -} - -struct VaapiVideoEncodeAccelerator::InputFrameRef { - InputFrameRef(const scoped_refptr<media::VideoFrame>& frame, - bool force_keyframe) - : frame(frame), force_keyframe(force_keyframe) {} - const scoped_refptr<media::VideoFrame> frame; - const bool force_keyframe; -}; - -struct VaapiVideoEncodeAccelerator::BitstreamBufferRef { - BitstreamBufferRef(int32 id, scoped_ptr<base::SharedMemory> shm, size_t size) - : id(id), shm(shm.Pass()), size(size) {} - const int32 id; - const scoped_ptr<base::SharedMemory> shm; - const size_t size; -}; - -// static -std::vector<media::VideoEncodeAccelerator::SupportedProfile> -VaapiVideoEncodeAccelerator::GetSupportedProfiles() { - std::vector<SupportedProfile> profiles; - - const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); - if (!cmd_line->HasSwitch(switches::kEnableVaapiAcceleratedVideoEncode)) - return profiles; - - SupportedProfile profile; - profile.profile = media::H264PROFILE_MAIN; - profile.max_resolution.SetSize(1920, 1088); - profile.max_framerate.numerator = kDefaultFramerate; - profile.max_framerate.denominator = 1; - profiles.push_back(profile); - - // This is actually only constrained (see crbug.com/345569). - profile.profile = media::H264PROFILE_BASELINE; - profiles.push_back(profile); - - profile.profile = media::H264PROFILE_HIGH; - profiles.push_back(profile); - - return profiles; -} - -static unsigned int Log2OfPowerOf2(unsigned int x) { - CHECK_GT(x, 0u); - DCHECK_EQ(x & (x - 1), 0u); - - int log = 0; - while (x) { - x >>= 1; - ++log; - } - return log; -} - -VaapiVideoEncodeAccelerator::VaapiVideoEncodeAccelerator(Display* x_display) - : profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), - mb_width_(0), - mb_height_(0), - output_buffer_byte_size_(0), - x_display_(x_display), - state_(kUninitialized), - frame_num_(0), - last_idr_frame_num_(0), - bitrate_(0), - framerate_(0), - cpb_size_(0), - encoding_parameters_changed_(false), - encoder_thread_("VAVEAEncoderThread"), - child_message_loop_proxy_(base::MessageLoopProxy::current()), - weak_this_ptr_factory_(this) { - DVLOGF(4); - weak_this_ = weak_this_ptr_factory_.GetWeakPtr(); - - max_ref_idx_l0_size_ = kMaxNumReferenceFrames; - qp_ = kDefaultQP; - idr_period_ = kIDRPeriod; - i_period_ = kIPeriod; - ip_period_ = kIPPeriod; -} - -VaapiVideoEncodeAccelerator::~VaapiVideoEncodeAccelerator() { - DVLOGF(4); - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - DCHECK(!encoder_thread_.IsRunning()); -} - -bool VaapiVideoEncodeAccelerator::Initialize( - media::VideoFrame::Format format, - const gfx::Size& input_visible_size, - media::VideoCodecProfile output_profile, - uint32 initial_bitrate, - Client* client) { - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - DCHECK(!encoder_thread_.IsRunning()); - DCHECK_EQ(state_, kUninitialized); - - DVLOGF(1) << "Initializing VAVEA, input_format: " - << media::VideoFrame::FormatToString(format) - << ", input_visible_size: " << input_visible_size.ToString() - << ", output_profile: " << output_profile - << ", initial_bitrate: " << initial_bitrate; - - client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); - client_ = client_ptr_factory_->GetWeakPtr(); - - if (output_profile < media::H264PROFILE_BASELINE || - output_profile > media::H264PROFILE_MAIN) { - DVLOGF(1) << "Unsupported output profile: " << output_profile; - return false; - } - - if (format != media::VideoFrame::I420) { - DVLOGF(1) << "Unsupported input format: " - << media::VideoFrame::FormatToString(format); - return false; - } - - profile_ = output_profile; - visible_size_ = input_visible_size; - // 4:2:0 format has to be 2-aligned. - DCHECK_EQ(visible_size_.width() % 2, 0); - DCHECK_EQ(visible_size_.height() % 2, 0); - coded_size_ = gfx::Size(RoundUpToPowerOf2(visible_size_.width(), 16), - RoundUpToPowerOf2(visible_size_.height(), 16)); - mb_width_ = coded_size_.width() / 16; - mb_height_ = coded_size_.height() / 16; - output_buffer_byte_size_ = coded_size_.GetArea(); - - UpdateRates(initial_bitrate, kDefaultFramerate); - - vaapi_wrapper_ = VaapiWrapper::Create(VaapiWrapper::kEncode, - output_profile, - x_display_, - base::Bind(&ReportToUMA, VAAPI_ERROR)); - if (!vaapi_wrapper_) { - DVLOGF(1) << "Failed initializing VAAPI"; - return false; - } - - if (!encoder_thread_.Start()) { - DVLOGF(1) << "Failed to start encoder thread"; - return false; - } - encoder_thread_proxy_ = encoder_thread_.message_loop_proxy(); - - // Finish the remaining initialization on the encoder thread. - encoder_thread_proxy_->PostTask( - FROM_HERE, - base::Bind(&VaapiVideoEncodeAccelerator::InitializeTask, - base::Unretained(this))); - - return true; -} - -void VaapiVideoEncodeAccelerator::InitializeTask() { - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - DCHECK_EQ(state_, kUninitialized); - DVLOGF(4); - - va_surface_release_cb_ = media::BindToCurrentLoop( - base::Bind(&VaapiVideoEncodeAccelerator::RecycleVASurfaceID, - base::Unretained(this))); - - if (!vaapi_wrapper_->CreateSurfaces( - coded_size_, kNumSurfaces, &available_va_surface_ids_)) { - NOTIFY_ERROR(kPlatformFailureError, "Failed creating VASurfaces"); - return; - } - - UpdateSPS(); - GeneratePackedSPS(); - - UpdatePPS(); - GeneratePackedPPS(); - - child_message_loop_proxy_->PostTask( - FROM_HERE, - base::Bind(&Client::RequireBitstreamBuffers, - client_, - kNumInputBuffers, - coded_size_, - output_buffer_byte_size_)); - - SetState(kEncoding); -} - -void VaapiVideoEncodeAccelerator::RecycleVASurfaceID( - VASurfaceID va_surface_id) { - DVLOGF(4) << "va_surface_id: " << va_surface_id; - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - - available_va_surface_ids_.push_back(va_surface_id); - EncodeFrameTask(); -} - -void VaapiVideoEncodeAccelerator::BeginFrame(bool force_keyframe) { - memset(¤t_pic_, 0, sizeof(current_pic_)); - - current_pic_.frame_num = frame_num_++; - frame_num_ %= idr_period_; - - if (current_pic_.frame_num % i_period_ == 0 || force_keyframe) - current_pic_.type = media::H264SliceHeader::kISlice; - else - current_pic_.type = media::H264SliceHeader::kPSlice; - - if (current_pic_.frame_num % idr_period_ == 0) { - current_pic_.idr = true; - last_idr_frame_num_ = current_pic_.frame_num; - ref_pic_list0_.clear(); - } - - if (current_pic_.type != media::H264SliceHeader::kBSlice) - current_pic_.ref = true; - - current_pic_.pic_order_cnt = current_pic_.frame_num * 2; - current_pic_.top_field_order_cnt = current_pic_.pic_order_cnt; - current_pic_.pic_order_cnt_lsb = current_pic_.pic_order_cnt; - - current_encode_job_->keyframe = - (current_pic_.type == media::H264SliceHeader::kISlice); - - DVLOGF(4) << "Starting a new frame, type: " << current_pic_.type - << (force_keyframe ? " (forced keyframe)" : "") - << " frame_num: " << current_pic_.frame_num - << " POC: " << current_pic_.pic_order_cnt; -} - -void VaapiVideoEncodeAccelerator::EndFrame() { - // Store the picture on the list of reference pictures and keep the list - // below maximum size, dropping oldest references. - if (current_pic_.ref) - ref_pic_list0_.push_front(current_encode_job_->recon_surface); - size_t max_num_ref_frames = - base::checked_cast<size_t>(current_sps_.max_num_ref_frames); - while (ref_pic_list0_.size() > max_num_ref_frames) - ref_pic_list0_.pop_back(); - - submitted_encode_jobs_.push(make_linked_ptr(current_encode_job_.release())); -} - -static void InitVAPicture(VAPictureH264* va_pic) { - memset(va_pic, 0, sizeof(*va_pic)); - va_pic->picture_id = VA_INVALID_ID; - va_pic->flags = VA_PICTURE_H264_INVALID; -} - -bool VaapiVideoEncodeAccelerator::SubmitFrameParameters() { - VAEncSequenceParameterBufferH264 seq_param; - memset(&seq_param, 0, sizeof(seq_param)); - -#define SPS_TO_SP(a) seq_param.a = current_sps_.a; - SPS_TO_SP(seq_parameter_set_id); - SPS_TO_SP(level_idc); - - seq_param.intra_period = i_period_; - seq_param.intra_idr_period = idr_period_; - seq_param.ip_period = ip_period_; - seq_param.bits_per_second = bitrate_; - - SPS_TO_SP(max_num_ref_frames); - seq_param.picture_width_in_mbs = mb_width_; - seq_param.picture_height_in_mbs = mb_height_; - -#define SPS_TO_SP_FS(a) seq_param.seq_fields.bits.a = current_sps_.a; - SPS_TO_SP_FS(chroma_format_idc); - SPS_TO_SP_FS(frame_mbs_only_flag); - SPS_TO_SP_FS(log2_max_frame_num_minus4); - SPS_TO_SP_FS(pic_order_cnt_type); - SPS_TO_SP_FS(log2_max_pic_order_cnt_lsb_minus4); -#undef SPS_TO_SP_FS - - SPS_TO_SP(bit_depth_luma_minus8); - SPS_TO_SP(bit_depth_chroma_minus8); - - SPS_TO_SP(frame_cropping_flag); - if (current_sps_.frame_cropping_flag) { - SPS_TO_SP(frame_crop_left_offset); - SPS_TO_SP(frame_crop_right_offset); - SPS_TO_SP(frame_crop_top_offset); - SPS_TO_SP(frame_crop_bottom_offset); - } - - SPS_TO_SP(vui_parameters_present_flag); -#define SPS_TO_SP_VF(a) seq_param.vui_fields.bits.a = current_sps_.a; - SPS_TO_SP_VF(timing_info_present_flag); -#undef SPS_TO_SP_VF - SPS_TO_SP(num_units_in_tick); - SPS_TO_SP(time_scale); -#undef SPS_TO_SP - - if (!vaapi_wrapper_->SubmitBuffer(VAEncSequenceParameterBufferType, - sizeof(seq_param), - &seq_param)) - return false; - - VAEncPictureParameterBufferH264 pic_param; - memset(&pic_param, 0, sizeof(pic_param)); - - pic_param.CurrPic.picture_id = current_encode_job_->recon_surface->id(); - pic_param.CurrPic.TopFieldOrderCnt = current_pic_.top_field_order_cnt; - pic_param.CurrPic.BottomFieldOrderCnt = current_pic_.bottom_field_order_cnt; - pic_param.CurrPic.flags = 0; - - for (size_t i = 0; i < arraysize(pic_param.ReferenceFrames); ++i) - InitVAPicture(&pic_param.ReferenceFrames[i]); - - DCHECK_LE(ref_pic_list0_.size(), arraysize(pic_param.ReferenceFrames)); - RefPicList::const_iterator iter = ref_pic_list0_.begin(); - for (size_t i = 0; - i < arraysize(pic_param.ReferenceFrames) && iter != ref_pic_list0_.end(); - ++iter, ++i) { - pic_param.ReferenceFrames[i].picture_id = (*iter)->id(); - pic_param.ReferenceFrames[i].flags = 0; - } - - pic_param.coded_buf = current_encode_job_->coded_buffer; - pic_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id; - pic_param.seq_parameter_set_id = current_pps_.seq_parameter_set_id; - pic_param.frame_num = current_pic_.frame_num; - pic_param.pic_init_qp = qp_; - pic_param.num_ref_idx_l0_active_minus1 = max_ref_idx_l0_size_ - 1; - pic_param.pic_fields.bits.idr_pic_flag = current_pic_.idr; - pic_param.pic_fields.bits.reference_pic_flag = current_pic_.ref; -#define PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = current_pps_.a; - PPS_TO_PP_PF(entropy_coding_mode_flag); - PPS_TO_PP_PF(transform_8x8_mode_flag); - PPS_TO_PP_PF(deblocking_filter_control_present_flag); -#undef PPS_TO_PP_PF - - if (!vaapi_wrapper_->SubmitBuffer(VAEncPictureParameterBufferType, - sizeof(pic_param), - &pic_param)) - return false; - - VAEncSliceParameterBufferH264 slice_param; - memset(&slice_param, 0, sizeof(slice_param)); - - slice_param.num_macroblocks = mb_width_ * mb_height_; - slice_param.macroblock_info = VA_INVALID_ID; - slice_param.slice_type = current_pic_.type; - slice_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id; - slice_param.idr_pic_id = last_idr_frame_num_; - slice_param.pic_order_cnt_lsb = current_pic_.pic_order_cnt_lsb; - slice_param.num_ref_idx_active_override_flag = true; - - for (size_t i = 0; i < arraysize(slice_param.RefPicList0); ++i) - InitVAPicture(&slice_param.RefPicList0[i]); - - for (size_t i = 0; i < arraysize(slice_param.RefPicList1); ++i) - InitVAPicture(&slice_param.RefPicList1[i]); - - DCHECK_LE(ref_pic_list0_.size(), arraysize(slice_param.RefPicList0)); - iter = ref_pic_list0_.begin(); - for (size_t i = 0; - i < arraysize(slice_param.RefPicList0) && iter != ref_pic_list0_.end(); - ++iter, ++i) { - InitVAPicture(&slice_param.RefPicList0[i]); - slice_param.RefPicList0[i].picture_id = (*iter)->id(); - slice_param.RefPicList0[i].flags = 0; - } - - if (!vaapi_wrapper_->SubmitBuffer(VAEncSliceParameterBufferType, - sizeof(slice_param), - &slice_param)) - return false; - - VAEncMiscParameterRateControl rate_control_param; - memset(&rate_control_param, 0, sizeof(rate_control_param)); - rate_control_param.bits_per_second = bitrate_; - rate_control_param.target_percentage = 90; - rate_control_param.window_size = kCPBWindowSizeMs; - rate_control_param.initial_qp = qp_; - rate_control_param.rc_flags.bits.disable_frame_skip = true; - - if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer( - VAEncMiscParameterTypeRateControl, - sizeof(rate_control_param), - &rate_control_param)) - return false; - - VAEncMiscParameterFrameRate framerate_param; - memset(&framerate_param, 0, sizeof(framerate_param)); - framerate_param.framerate = framerate_; - if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer( - VAEncMiscParameterTypeFrameRate, - sizeof(framerate_param), - &framerate_param)) - return false; - - VAEncMiscParameterHRD hrd_param; - memset(&hrd_param, 0, sizeof(hrd_param)); - hrd_param.buffer_size = cpb_size_; - hrd_param.initial_buffer_fullness = cpb_size_ / 2; - if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer(VAEncMiscParameterTypeHRD, - sizeof(hrd_param), - &hrd_param)) - return false; - - return true; -} - -bool VaapiVideoEncodeAccelerator::SubmitHeadersIfNeeded() { - if (current_pic_.type != media::H264SliceHeader::kISlice) - return true; - - // Submit PPS. - VAEncPackedHeaderParameterBuffer par_buffer; - memset(&par_buffer, 0, sizeof(par_buffer)); - par_buffer.type = VAEncPackedHeaderSequence; - par_buffer.bit_length = packed_sps_.BytesInBuffer() * 8; - - if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderParameterBufferType, - sizeof(par_buffer), - &par_buffer)) - return false; - - if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType, - packed_sps_.BytesInBuffer(), - packed_sps_.data())) - return false; - - // Submit PPS. - memset(&par_buffer, 0, sizeof(par_buffer)); - par_buffer.type = VAEncPackedHeaderPicture; - par_buffer.bit_length = packed_pps_.BytesInBuffer() * 8; - - if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderParameterBufferType, - sizeof(par_buffer), - &par_buffer)) - return false; - - if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType, - packed_pps_.BytesInBuffer(), - packed_pps_.data())) - return false; - - return true; -} - -bool VaapiVideoEncodeAccelerator::ExecuteEncode() { - DVLOGF(3) << "Encoding frame_num: " << current_pic_.frame_num; - return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( - current_encode_job_->input_surface->id()); -} - -bool VaapiVideoEncodeAccelerator::UploadFrame( - const scoped_refptr<media::VideoFrame>& frame) { - return vaapi_wrapper_->UploadVideoFrameToSurface( - frame, current_encode_job_->input_surface->id()); -} - -void VaapiVideoEncodeAccelerator::TryToReturnBitstreamBuffer() { - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - - if (state_ != kEncoding) - return; - - if (submitted_encode_jobs_.empty() || available_bitstream_buffers_.empty()) - return; - - linked_ptr<BitstreamBufferRef> buffer = available_bitstream_buffers_.front(); - available_bitstream_buffers_.pop(); - - uint8* target_data = reinterpret_cast<uint8*>(buffer->shm->memory()); - - linked_ptr<EncodeJob> encode_job = submitted_encode_jobs_.front(); - submitted_encode_jobs_.pop(); - - size_t data_size = 0; - if (!vaapi_wrapper_->DownloadAndDestroyCodedBuffer( - encode_job->coded_buffer, - encode_job->input_surface->id(), - target_data, - buffer->size, - &data_size)) { - NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer"); - return; - } - - DVLOGF(3) << "Returning bitstream buffer " - << (encode_job->keyframe ? "(keyframe)" : "") - << " id: " << buffer->id << " size: " << data_size; - - child_message_loop_proxy_->PostTask(FROM_HERE, - base::Bind(&Client::BitstreamBufferReady, - client_, - buffer->id, - data_size, - encode_job->keyframe)); -} - -void VaapiVideoEncodeAccelerator::Encode( - const scoped_refptr<media::VideoFrame>& frame, - bool force_keyframe) { - DVLOGF(3) << "Frame timestamp: " << frame->timestamp().InMilliseconds() - << " force_keyframe: " << force_keyframe; - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - - encoder_thread_proxy_->PostTask( - FROM_HERE, - base::Bind(&VaapiVideoEncodeAccelerator::EncodeTask, - base::Unretained(this), - frame, - force_keyframe)); -} - -bool VaapiVideoEncodeAccelerator::PrepareNextJob() { - if (available_va_surface_ids_.size() < kMinSurfacesToEncode) - return false; - - DCHECK(!current_encode_job_); - current_encode_job_.reset(new EncodeJob()); - - if (!vaapi_wrapper_->CreateCodedBuffer(output_buffer_byte_size_, - ¤t_encode_job_->coded_buffer)) { - NOTIFY_ERROR(kPlatformFailureError, "Failed creating coded buffer"); - return false; - } - - current_encode_job_->input_surface = - new VASurface(available_va_surface_ids_.back(), va_surface_release_cb_); - available_va_surface_ids_.pop_back(); - - current_encode_job_->recon_surface = - new VASurface(available_va_surface_ids_.back(), va_surface_release_cb_); - available_va_surface_ids_.pop_back(); - - // Reference surfaces are needed until the job is done, but they get - // removed from ref_pic_list0_ when it's full at the end of job submission. - // Keep refs to them along with the job and only release after sync. - current_encode_job_->reference_surfaces = ref_pic_list0_; - - return true; -} - -void VaapiVideoEncodeAccelerator::EncodeTask( - const scoped_refptr<media::VideoFrame>& frame, - bool force_keyframe) { - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - DCHECK_NE(state_, kUninitialized); - - encoder_input_queue_.push( - make_linked_ptr(new InputFrameRef(frame, force_keyframe))); - EncodeFrameTask(); -} - -void VaapiVideoEncodeAccelerator::EncodeFrameTask() { - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - - if (state_ != kEncoding || encoder_input_queue_.empty()) - return; - - if (!PrepareNextJob()) { - DVLOGF(4) << "Not ready for next frame yet"; - return; - } - - linked_ptr<InputFrameRef> frame_ref = encoder_input_queue_.front(); - encoder_input_queue_.pop(); - - if (!UploadFrame(frame_ref->frame)) { - NOTIFY_ERROR(kPlatformFailureError, "Failed uploading source frame to HW."); - return; - } - - BeginFrame(frame_ref->force_keyframe || encoding_parameters_changed_); - encoding_parameters_changed_ = false; - - if (!SubmitFrameParameters()) { - NOTIFY_ERROR(kPlatformFailureError, "Failed submitting frame parameters."); - return; - } - - if (!SubmitHeadersIfNeeded()) { - NOTIFY_ERROR(kPlatformFailureError, "Failed submitting frame headers."); - return; - } - - if (!ExecuteEncode()) { - NOTIFY_ERROR(kPlatformFailureError, "Failed submitting encode job to HW."); - return; - } - - EndFrame(); - TryToReturnBitstreamBuffer(); -} - -void VaapiVideoEncodeAccelerator::UseOutputBitstreamBuffer( - const media::BitstreamBuffer& buffer) { - DVLOGF(4) << "id: " << buffer.id(); - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - - if (buffer.size() < output_buffer_byte_size_) { - NOTIFY_ERROR(kInvalidArgumentError, "Provided bitstream buffer too small"); - return; - } - - scoped_ptr<base::SharedMemory> shm( - new base::SharedMemory(buffer.handle(), false)); - if (!shm->Map(buffer.size())) { - NOTIFY_ERROR(kPlatformFailureError, "Failed mapping shared memory."); - return; - } - - scoped_ptr<BitstreamBufferRef> buffer_ref( - new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size())); - - encoder_thread_proxy_->PostTask( - FROM_HERE, - base::Bind(&VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask, - base::Unretained(this), - base::Passed(&buffer_ref))); -} - -void VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask( - scoped_ptr<BitstreamBufferRef> buffer_ref) { - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - DCHECK_NE(state_, kUninitialized); - - available_bitstream_buffers_.push(make_linked_ptr(buffer_ref.release())); - TryToReturnBitstreamBuffer(); -} - -void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange( - uint32 bitrate, - uint32 framerate) { - DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate; - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - - encoder_thread_proxy_->PostTask( - FROM_HERE, - base::Bind( - &VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask, - base::Unretained(this), - bitrate, - framerate)); -} - -void VaapiVideoEncodeAccelerator::UpdateRates(uint32 bitrate, - uint32 framerate) { - if (encoder_thread_.IsRunning()) - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - DCHECK_NE(bitrate, 0u); - DCHECK_NE(framerate, 0u); - bitrate_ = bitrate; - framerate_ = framerate; - cpb_size_ = bitrate_ * kCPBWindowSizeMs / 1000; -} - -void VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask( - uint32 bitrate, - uint32 framerate) { - DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate; - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - DCHECK_NE(state_, kUninitialized); - - UpdateRates(bitrate, framerate); - - UpdateSPS(); - GeneratePackedSPS(); - - // Submit new parameters along with next frame that will be processed. - encoding_parameters_changed_ = true; -} - -void VaapiVideoEncodeAccelerator::Destroy() { - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - - // Can't call client anymore after Destroy() returns. - client_ptr_factory_.reset(); - weak_this_ptr_factory_.InvalidateWeakPtrs(); - - // Early-exit encoder tasks if they are running and join the thread. - if (encoder_thread_.IsRunning()) { - encoder_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&VaapiVideoEncodeAccelerator::DestroyTask, - base::Unretained(this))); - encoder_thread_.Stop(); - } - - delete this; -} - -void VaapiVideoEncodeAccelerator::DestroyTask() { - DVLOGF(2); - DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); - SetState(kError); -} - -void VaapiVideoEncodeAccelerator::UpdateSPS() { - memset(¤t_sps_, 0, sizeof(media::H264SPS)); - - // Spec A.2 and A.3. - switch (profile_) { - case media::H264PROFILE_BASELINE: - // Due to crbug.com/345569, we don't distinguish between constrained - // and non-constrained baseline profiles. Since many codecs can't do - // non-constrained, and constrained is usually what we mean (and it's a - // subset of non-constrained), default to it. - current_sps_.profile_idc = media::H264SPS::kProfileIDCBaseline; - current_sps_.constraint_set0_flag = true; - break; - case media::H264PROFILE_MAIN: - current_sps_.profile_idc = media::H264SPS::kProfileIDCMain; - current_sps_.constraint_set1_flag = true; - break; - case media::H264PROFILE_HIGH: - current_sps_.profile_idc = media::H264SPS::kProfileIDCHigh; - break; - default: - NOTIMPLEMENTED(); - return; - } - - current_sps_.level_idc = kDefaultLevelIDC; - current_sps_.seq_parameter_set_id = 0; - current_sps_.chroma_format_idc = kChromaFormatIDC; - - DCHECK_GE(idr_period_, 1u << 4); - current_sps_.log2_max_frame_num_minus4 = Log2OfPowerOf2(idr_period_) - 4; - current_sps_.pic_order_cnt_type = 0; - current_sps_.log2_max_pic_order_cnt_lsb_minus4 = - Log2OfPowerOf2(idr_period_ * 2) - 4; - current_sps_.max_num_ref_frames = max_ref_idx_l0_size_; - - current_sps_.frame_mbs_only_flag = true; - - DCHECK_GT(mb_width_, 0u); - DCHECK_GT(mb_height_, 0u); - current_sps_.pic_width_in_mbs_minus1 = mb_width_ - 1; - DCHECK(current_sps_.frame_mbs_only_flag); - current_sps_.pic_height_in_map_units_minus1 = mb_height_ - 1; - - if (visible_size_ != coded_size_) { - // Visible size differs from coded size, fill crop information. - current_sps_.frame_cropping_flag = true; - DCHECK(!current_sps_.separate_colour_plane_flag); - // Spec table 6-1. Only 4:2:0 for now. - DCHECK_EQ(current_sps_.chroma_format_idc, 1); - // Spec 7.4.2.1.1. Crop is in crop units, which is 2 pixels for 4:2:0. - const unsigned int crop_unit_x = 2; - const unsigned int crop_unit_y = 2 * (2 - current_sps_.frame_mbs_only_flag); - current_sps_.frame_crop_left_offset = 0; - current_sps_.frame_crop_right_offset = - (coded_size_.width() - visible_size_.width()) / crop_unit_x; - current_sps_.frame_crop_top_offset = 0; - current_sps_.frame_crop_bottom_offset = - (coded_size_.height() - visible_size_.height()) / crop_unit_y; - } - - current_sps_.vui_parameters_present_flag = true; - current_sps_.timing_info_present_flag = true; - current_sps_.num_units_in_tick = 1; - current_sps_.time_scale = framerate_ * 2; // See equation D-2 in spec. - current_sps_.fixed_frame_rate_flag = true; - - current_sps_.nal_hrd_parameters_present_flag = true; - // H.264 spec ch. E.2.2. - current_sps_.cpb_cnt_minus1 = 0; - current_sps_.bit_rate_scale = kBitRateScale; - current_sps_.cpb_size_scale = kCPBSizeScale; - current_sps_.bit_rate_value_minus1[0] = - (bitrate_ >> - (kBitRateScale + media::H264SPS::kBitRateScaleConstantTerm)) - 1; - current_sps_.cpb_size_value_minus1[0] = - (cpb_size_ >> - (kCPBSizeScale + media::H264SPS::kCPBSizeScaleConstantTerm)) - 1; - current_sps_.cbr_flag[0] = true; - current_sps_.initial_cpb_removal_delay_length_minus_1 = - media::H264SPS::kDefaultInitialCPBRemovalDelayLength - 1; - current_sps_.cpb_removal_delay_length_minus1 = - media::H264SPS::kDefaultInitialCPBRemovalDelayLength - 1; - current_sps_.dpb_output_delay_length_minus1 = - media::H264SPS::kDefaultDPBOutputDelayLength - 1; - current_sps_.time_offset_length = media::H264SPS::kDefaultTimeOffsetLength; - current_sps_.low_delay_hrd_flag = false; -} - -void VaapiVideoEncodeAccelerator::GeneratePackedSPS() { - packed_sps_.Reset(); - - packed_sps_.BeginNALU(media::H264NALU::kSPS, 3); - - packed_sps_.AppendBits(8, current_sps_.profile_idc); - packed_sps_.AppendBool(current_sps_.constraint_set0_flag); - packed_sps_.AppendBool(current_sps_.constraint_set1_flag); - packed_sps_.AppendBool(current_sps_.constraint_set2_flag); - packed_sps_.AppendBool(current_sps_.constraint_set3_flag); - packed_sps_.AppendBool(current_sps_.constraint_set4_flag); - packed_sps_.AppendBool(current_sps_.constraint_set5_flag); - packed_sps_.AppendBits(2, 0); // reserved_zero_2bits - packed_sps_.AppendBits(8, current_sps_.level_idc); - packed_sps_.AppendUE(current_sps_.seq_parameter_set_id); - - if (current_sps_.profile_idc == media::H264SPS::kProfileIDCHigh) { - packed_sps_.AppendUE(current_sps_.chroma_format_idc); - if (current_sps_.chroma_format_idc == 3) - packed_sps_.AppendBool(current_sps_.separate_colour_plane_flag); - packed_sps_.AppendUE(current_sps_.bit_depth_luma_minus8); - packed_sps_.AppendUE(current_sps_.bit_depth_chroma_minus8); - packed_sps_.AppendBool(current_sps_.qpprime_y_zero_transform_bypass_flag); - packed_sps_.AppendBool(current_sps_.seq_scaling_matrix_present_flag); - CHECK(!current_sps_.seq_scaling_matrix_present_flag); - } - - packed_sps_.AppendUE(current_sps_.log2_max_frame_num_minus4); - packed_sps_.AppendUE(current_sps_.pic_order_cnt_type); - if (current_sps_.pic_order_cnt_type == 0) - packed_sps_.AppendUE(current_sps_.log2_max_pic_order_cnt_lsb_minus4); - else if (current_sps_.pic_order_cnt_type == 1) { - CHECK(1); - } - - packed_sps_.AppendUE(current_sps_.max_num_ref_frames); - packed_sps_.AppendBool(current_sps_.gaps_in_frame_num_value_allowed_flag); - packed_sps_.AppendUE(current_sps_.pic_width_in_mbs_minus1); - packed_sps_.AppendUE(current_sps_.pic_height_in_map_units_minus1); - - packed_sps_.AppendBool(current_sps_.frame_mbs_only_flag); - if (!current_sps_.frame_mbs_only_flag) - packed_sps_.AppendBool(current_sps_.mb_adaptive_frame_field_flag); - - packed_sps_.AppendBool(current_sps_.direct_8x8_inference_flag); - - packed_sps_.AppendBool(current_sps_.frame_cropping_flag); - if (current_sps_.frame_cropping_flag) { - packed_sps_.AppendUE(current_sps_.frame_crop_left_offset); - packed_sps_.AppendUE(current_sps_.frame_crop_right_offset); - packed_sps_.AppendUE(current_sps_.frame_crop_top_offset); - packed_sps_.AppendUE(current_sps_.frame_crop_bottom_offset); - } - - packed_sps_.AppendBool(current_sps_.vui_parameters_present_flag); - if (current_sps_.vui_parameters_present_flag) { - packed_sps_.AppendBool(false); // aspect_ratio_info_present_flag - packed_sps_.AppendBool(false); // overscan_info_present_flag - packed_sps_.AppendBool(false); // video_signal_type_present_flag - packed_sps_.AppendBool(false); // chroma_loc_info_present_flag - - packed_sps_.AppendBool(current_sps_.timing_info_present_flag); - if (current_sps_.timing_info_present_flag) { - packed_sps_.AppendBits(32, current_sps_.num_units_in_tick); - packed_sps_.AppendBits(32, current_sps_.time_scale); - packed_sps_.AppendBool(current_sps_.fixed_frame_rate_flag); - } - - packed_sps_.AppendBool(current_sps_.nal_hrd_parameters_present_flag); - if (current_sps_.nal_hrd_parameters_present_flag) { - packed_sps_.AppendUE(current_sps_.cpb_cnt_minus1); - packed_sps_.AppendBits(4, current_sps_.bit_rate_scale); - packed_sps_.AppendBits(4, current_sps_.cpb_size_scale); - CHECK_LT(base::checked_cast<size_t>(current_sps_.cpb_cnt_minus1), - arraysize(current_sps_.bit_rate_value_minus1)); - for (int i = 0; i <= current_sps_.cpb_cnt_minus1; ++i) { - packed_sps_.AppendUE(current_sps_.bit_rate_value_minus1[i]); - packed_sps_.AppendUE(current_sps_.cpb_size_value_minus1[i]); - packed_sps_.AppendBool(current_sps_.cbr_flag[i]); - } - packed_sps_.AppendBits( - 5, current_sps_.initial_cpb_removal_delay_length_minus_1); - packed_sps_.AppendBits(5, current_sps_.cpb_removal_delay_length_minus1); - packed_sps_.AppendBits(5, current_sps_.dpb_output_delay_length_minus1); - packed_sps_.AppendBits(5, current_sps_.time_offset_length); - } - - packed_sps_.AppendBool(false); // vcl_hrd_parameters_flag - if (current_sps_.nal_hrd_parameters_present_flag) - packed_sps_.AppendBool(current_sps_.low_delay_hrd_flag); - - packed_sps_.AppendBool(false); // pic_struct_present_flag - packed_sps_.AppendBool(false); // bitstream_restriction_flag - } - - packed_sps_.FinishNALU(); -} - -void VaapiVideoEncodeAccelerator::UpdatePPS() { - memset(¤t_pps_, 0, sizeof(media::H264PPS)); - - current_pps_.seq_parameter_set_id = current_sps_.seq_parameter_set_id; - current_pps_.pic_parameter_set_id = 0; - - current_pps_.entropy_coding_mode_flag = - current_sps_.profile_idc >= media::H264SPS::kProfileIDCMain; - - CHECK_GT(max_ref_idx_l0_size_, 0u); - current_pps_.num_ref_idx_l0_default_active_minus1 = max_ref_idx_l0_size_ - 1; - current_pps_.num_ref_idx_l1_default_active_minus1 = 0; - DCHECK_LE(qp_, 51u); - current_pps_.pic_init_qp_minus26 = qp_ - 26; - current_pps_.deblocking_filter_control_present_flag = true; - current_pps_.transform_8x8_mode_flag = - (current_sps_.profile_idc == media::H264SPS::kProfileIDCHigh); -} - -void VaapiVideoEncodeAccelerator::GeneratePackedPPS() { - packed_pps_.Reset(); - - packed_pps_.BeginNALU(media::H264NALU::kPPS, 3); - - packed_pps_.AppendUE(current_pps_.pic_parameter_set_id); - packed_pps_.AppendUE(current_pps_.seq_parameter_set_id); - packed_pps_.AppendBool(current_pps_.entropy_coding_mode_flag); - packed_pps_.AppendBool( - current_pps_.bottom_field_pic_order_in_frame_present_flag); - CHECK_EQ(current_pps_.num_slice_groups_minus1, 0); - packed_pps_.AppendUE(current_pps_.num_slice_groups_minus1); - - packed_pps_.AppendUE(current_pps_.num_ref_idx_l0_default_active_minus1); - packed_pps_.AppendUE(current_pps_.num_ref_idx_l1_default_active_minus1); - - packed_pps_.AppendBool(current_pps_.weighted_pred_flag); - packed_pps_.AppendBits(2, current_pps_.weighted_bipred_idc); - - packed_pps_.AppendSE(current_pps_.pic_init_qp_minus26); - packed_pps_.AppendSE(current_pps_.pic_init_qs_minus26); - packed_pps_.AppendSE(current_pps_.chroma_qp_index_offset); - - packed_pps_.AppendBool(current_pps_.deblocking_filter_control_present_flag); - packed_pps_.AppendBool(current_pps_.constrained_intra_pred_flag); - packed_pps_.AppendBool(current_pps_.redundant_pic_cnt_present_flag); - - packed_pps_.AppendBool(current_pps_.transform_8x8_mode_flag); - packed_pps_.AppendBool(current_pps_.pic_scaling_matrix_present_flag); - DCHECK(!current_pps_.pic_scaling_matrix_present_flag); - packed_pps_.AppendSE(current_pps_.second_chroma_qp_index_offset); - - packed_pps_.FinishNALU(); -} - -void VaapiVideoEncodeAccelerator::SetState(State state) { - // Only touch state on encoder thread, unless it's not running. - if (encoder_thread_.IsRunning() && - !encoder_thread_proxy_->BelongsToCurrentThread()) { - encoder_thread_proxy_->PostTask( - FROM_HERE, - base::Bind(&VaapiVideoEncodeAccelerator::SetState, - base::Unretained(this), - state)); - return; - } - - DVLOGF(1) << "setting state to: " << state; - state_ = state; -} - -void VaapiVideoEncodeAccelerator::NotifyError(Error error) { - if (!child_message_loop_proxy_->BelongsToCurrentThread()) { - child_message_loop_proxy_->PostTask( - FROM_HERE, - base::Bind( - &VaapiVideoEncodeAccelerator::NotifyError, weak_this_, error)); - return; - } - - if (client_) { - client_->NotifyError(error); - client_ptr_factory_.reset(); - } -} - -VaapiVideoEncodeAccelerator::EncodeJob::EncodeJob() - : coded_buffer(VA_INVALID_ID), keyframe(false) { -} - -VaapiVideoEncodeAccelerator::EncodeJob::~EncodeJob() { -} - -} // namespace content diff --git a/content/common/gpu/media/vaapi_video_encode_accelerator.h b/content/common/gpu/media/vaapi_video_encode_accelerator.h deleted file mode 100644 index 8a7811a..0000000 --- a/content/common/gpu/media/vaapi_video_encode_accelerator.h +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 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. - -#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_ -#define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_ - -#include <list> -#include <queue> - -#include "base/memory/linked_ptr.h" -#include "base/threading/thread.h" -#include "content/common/content_export.h" -#include "content/common/gpu/media/h264_dpb.h" -#include "content/common/gpu/media/va_surface.h" -#include "content/common/gpu/media/vaapi_wrapper.h" -#include "media/filters/h264_bitstream_buffer.h" -#include "media/video/video_encode_accelerator.h" - -namespace content { - -// A VideoEncodeAccelerator implementation that uses VA-API -// (http://www.freedesktop.org/wiki/Software/vaapi) for HW-accelerated -// video encode. -class CONTENT_EXPORT VaapiVideoEncodeAccelerator - : public media::VideoEncodeAccelerator { - public: - explicit VaapiVideoEncodeAccelerator(Display* x_display); - virtual ~VaapiVideoEncodeAccelerator(); - - // media::VideoEncodeAccelerator implementation. - virtual bool Initialize(media::VideoFrame::Format format, - const gfx::Size& input_visible_size, - media::VideoCodecProfile output_profile, - uint32 initial_bitrate, - Client* client) OVERRIDE; - virtual void Encode(const scoped_refptr<media::VideoFrame>& frame, - bool force_keyframe) OVERRIDE; - virtual void UseOutputBitstreamBuffer( - const media::BitstreamBuffer& buffer) OVERRIDE; - virtual void RequestEncodingParametersChange(uint32 bitrate, - uint32 framerate) OVERRIDE; - virtual void Destroy() OVERRIDE; - - static std::vector<media::VideoEncodeAccelerator::SupportedProfile> - GetSupportedProfiles(); - - private: - // Reference picture list. - typedef std::list<scoped_refptr<VASurface> > RefPicList; - - // Encode job for one frame. Created when an input frame is awaiting and - // enough resources are available to proceed. Once the job is prepared and - // submitted to the hardware, it awaits on the submitted_encode_jobs_ queue - // for an output bitstream buffer to become available. Once one is ready, - // the encoded bytes are downloaded to it and job resources are released - // and become available for reuse. - struct EncodeJob { - // Input surface for video frame data. - scoped_refptr<VASurface> input_surface; - // Surface for a reconstructed picture, which is used for reference - // for subsequent frames. - scoped_refptr<VASurface> recon_surface; - // Buffer that will contain output bitstream for this frame. - VABufferID coded_buffer; - // Reference surfaces required to encode this picture. We keep references - // to them here, because we may discard some of them from ref_pic_list* - // before the HW job is done. - RefPicList reference_surfaces; - // True if this job will produce a keyframe. Used to report - // to BitstreamBufferReady(). - bool keyframe; - - EncodeJob(); - ~EncodeJob(); - }; - - // Encoder state. - enum State { - kUninitialized, - kEncoding, - kError, - }; - - // Holds input frames coming from the client ready to be encoded. - struct InputFrameRef; - // Holds output buffers coming from the client ready to be filled. - struct BitstreamBufferRef; - - // Tasks for each of the VEA interface calls to be executed on the - // encoder thread. - void InitializeTask(); - void EncodeTask(const scoped_refptr<media::VideoFrame>& frame, - bool force_keyframe); - void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref); - void RequestEncodingParametersChangeTask(uint32 bitrate, uint32 framerate); - void DestroyTask(); - - // Prepare and schedule an encode job if we have an input to encode - // and enough resources to proceed. - void EncodeFrameTask(); - - // Fill current_sps_/current_pps_ with current values. - void UpdateSPS(); - void UpdatePPS(); - void UpdateRates(uint32 bitrate, uint32 framerate); - - // Generate packed SPS and PPS in packed_sps_/packed_pps_, using - // values in current_sps_/current_pps_. - void GeneratePackedSPS(); - void GeneratePackedPPS(); - - // Check if we have sufficient resources for a new encode job, claim them and - // fill current_encode_job_ with them. - // Return false if we cannot start a new job yet, true otherwise. - bool PrepareNextJob(); - - // Begin a new frame, making it a keyframe if |force_keyframe| is true, - // updating current_pic_. - void BeginFrame(bool force_keyframe); - - // End current frame, updating reference picture lists and storing current - // job in the jobs awaiting completion on submitted_encode_jobs_. - void EndFrame(); - - // Submit parameters for the current frame to the hardware. - bool SubmitFrameParameters(); - // Submit keyframe headers to the hardware if the current frame is a keyframe. - bool SubmitHeadersIfNeeded(); - - // Upload image data from |frame| to the input surface for current job. - bool UploadFrame(const scoped_refptr<media::VideoFrame>& frame); - - // Execute encode in hardware. This does not block and will return before - // the job is finished. - bool ExecuteEncode(); - - // Callback that returns a no longer used VASurfaceID to - // available_va_surface_ids_ for reuse. - void RecycleVASurfaceID(VASurfaceID va_surface_id); - - // Tries to return a bitstream buffer if both a submitted job awaits to - // be completed and we have bitstream buffers from the client available - // to download the encoded data to. - void TryToReturnBitstreamBuffer(); - - // Puts the encoder into en error state and notifies client about the error. - void NotifyError(Error error); - - // Sets the encoder state on the correct thread. - void SetState(State state); - - // VaapiWrapper is the owner of all HW resources (surfaces and buffers) - // and will free them on destruction. - scoped_ptr<VaapiWrapper> vaapi_wrapper_; - - // Input profile and sizes. - media::VideoCodecProfile profile_; - gfx::Size visible_size_; - gfx::Size coded_size_; // Macroblock-aligned. - // Width/height in macroblocks. - unsigned int mb_width_; - unsigned int mb_height_; - - // Maximum size of the reference list 0. - unsigned int max_ref_idx_l0_size_; - - // Initial QP. - unsigned int qp_; - - // IDR frame period. - unsigned int idr_period_; - // I frame period. - unsigned int i_period_; - // IP period, i.e. how often do we need to have either an I or a P frame in - // the stream. Period of 1 means we can have no B frames. - unsigned int ip_period_; - - // Size in bytes required for input bitstream buffers. - size_t output_buffer_byte_size_; - - Display* x_display_; - - // All of the members below must be accessed on the encoder_thread_, - // while it is running. - - // Encoder state. Encode tasks will only run in kEncoding state. - State state_; - - // frame_num to be used for the next frame. - unsigned int frame_num_; - // frame_num of the previous IDR. - unsigned int last_idr_frame_num_; - - // Current bitrate in bps. - unsigned int bitrate_; - // Current fps. - unsigned int framerate_; - // CPB size in bits, i.e. bitrate in kbps * window size in ms/1000. - unsigned int cpb_size_; - // True if the parameters have changed and we need to submit a keyframe - // with updated parameters. - bool encoding_parameters_changed_; - - // Job currently being prepared for encode. - scoped_ptr<EncodeJob> current_encode_job_; - - // Current SPS, PPS and their packed versions. Packed versions are their NALUs - // in AnnexB format *without* emulation prevention three-byte sequences - // (those will be added by the driver). - media::H264SPS current_sps_; - media::H264BitstreamBuffer packed_sps_; - media::H264PPS current_pps_; - media::H264BitstreamBuffer packed_pps_; - - // Picture currently being prepared for encode. - H264Picture current_pic_; - - // VA surfaces available for reuse. - std::vector<VASurfaceID> available_va_surface_ids_; - - // VA buffers for coded frames. - std::vector<VABufferID> available_va_buffer_ids_; - - // Currently active reference surfaces. - RefPicList ref_pic_list0_; - - // Callback via which finished VA surfaces are returned to us. - VASurface::ReleaseCB va_surface_release_cb_; - - // VideoFrames passed from the client, waiting to be encoded. - std::queue<linked_ptr<InputFrameRef> > encoder_input_queue_; - - // BitstreamBuffers mapped, ready to be filled. - std::queue<linked_ptr<BitstreamBufferRef> > available_bitstream_buffers_; - - // Jobs submitted for encode, awaiting bitstream buffers to become available. - std::queue<linked_ptr<EncodeJob> > submitted_encode_jobs_; - - // Encoder thread. All tasks are executed on it. - base::Thread encoder_thread_; - scoped_refptr<base::MessageLoopProxy> encoder_thread_proxy_; - - const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_; - - // To expose client callbacks from VideoEncodeAccelerator. - // NOTE: all calls to these objects *MUST* be executed on - // child_message_loop_proxy_. - scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_; - base::WeakPtr<Client> client_; - - // WeakPtr to post from the encoder thread back to the ChildThread, as it may - // outlive this. Posting from the ChildThread using base::Unretained(this) - // to the encoder thread is safe, because |this| always outlives the encoder - // thread (it's a member of this class). - base::WeakPtr<VaapiVideoEncodeAccelerator> weak_this_; - base::WeakPtrFactory<VaapiVideoEncodeAccelerator> weak_this_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(VaapiVideoEncodeAccelerator); -}; - -} // namespace content - -#endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_ diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc index 5e93b99..5250e59 100644 --- a/content/common/gpu/media/vaapi_wrapper.cc +++ b/content/common/gpu/media/vaapi_wrapper.cc @@ -7,12 +7,10 @@ #include <dlfcn.h> #include "base/bind.h" -#include "base/callback_helpers.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" // Auto-generated for dlopen libva libraries #include "content/common/gpu/media/va_stubs.h" -#include "third_party/libyuv/include/libyuv.h" using content_common_gpu_media::kModuleVa; using content_common_gpu_media::InitializeStubs; @@ -45,18 +43,6 @@ static const base::FilePath::CharType kVaLib[] = namespace content { -// Config attributes common for both encode and decode. -static const VAConfigAttrib kCommonVAConfigAttribs[] = { - {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, -}; - -// Attributes required for encode. -static const VAConfigAttrib kEncodeVAConfigAttribs[] = { - {VAConfigAttribRateControl, VA_RC_CBR}, - {VAConfigAttribEncPackedHeaders, - VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, -}; - // Maps Profile enum values to VaProfile values. static VAProfile ProfileToVAProfile( media::VideoCodecProfile profile, @@ -120,20 +106,17 @@ VaapiWrapper::VaapiWrapper() VaapiWrapper::~VaapiWrapper() { DestroyPendingBuffers(); - DestroyCodedBuffers(); DestroySurfaces(); Deinitialize(); } scoped_ptr<VaapiWrapper> VaapiWrapper::Create( - CodecMode mode, media::VideoCodecProfile profile, Display* x_display, const base::Closure& report_error_to_uma_cb) { scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); - if (!vaapi_wrapper->Initialize( - mode, profile, x_display, report_error_to_uma_cb)) + if (!vaapi_wrapper->Initialize(profile, x_display, report_error_to_uma_cb)) vaapi_wrapper.reset(); return vaapi_wrapper.Pass(); @@ -151,8 +134,7 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; } -bool VaapiWrapper::Initialize(CodecMode mode, - media::VideoCodecProfile profile, +bool VaapiWrapper::Initialize(media::VideoCodecProfile profile, Display* x_display, const base::Closure& report_error_to_uma_cb) { static bool vaapi_functions_initialized = PostSandboxInitialization(); @@ -202,73 +184,21 @@ bool VaapiWrapper::Initialize(CodecMode mode, return false; } - // Query the driver for supported entrypoints. - int max_entrypoints = vaMaxNumEntrypoints(va_display_); - std::vector<VAEntrypoint> supported_entrypoints( - base::checked_cast<size_t>(max_entrypoints)); - - int num_supported_entrypoints; - va_res = vaQueryConfigEntrypoints(va_display_, - va_profile, - &supported_entrypoints[0], - &num_supported_entrypoints); - VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); - if (num_supported_entrypoints < 0 || - num_supported_entrypoints > max_entrypoints) { - DVLOG(1) << "vaQueryConfigEntrypoints returned: " - << num_supported_entrypoints; - return false; - } - - VAEntrypoint entrypoint = - (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); - - if (std::find(supported_entrypoints.begin(), - supported_entrypoints.end(), - entrypoint) == supported_entrypoints.end()) { - DVLOG(1) << "Unsupported entrypoint"; - return false; - } - - // Query the driver for required attributes. - std::vector<VAConfigAttrib> required_attribs; - required_attribs.insert( - required_attribs.end(), - kCommonVAConfigAttribs, - kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); - if (mode == kEncode) { - required_attribs.insert( - required_attribs.end(), - kEncodeVAConfigAttribs, - kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); - } - - std::vector<VAConfigAttrib> attribs = required_attribs; - for (size_t i = 0; i < required_attribs.size(); ++i) - attribs[i].value = 0; - - va_res = vaGetConfigAttributes( - va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); + VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0}; + const VAEntrypoint kEntrypoint = VAEntrypointVLD; + va_res = vaGetConfigAttributes(va_display_, va_profile, kEntrypoint, + &attrib, 1); VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); - for (size_t i = 0; i < required_attribs.size(); ++i) { - if (attribs[i].type != required_attribs[i].type || - (attribs[i].value & required_attribs[i].value) != - required_attribs[i].value) { - DVLOG(1) << "Unsupported value " << required_attribs[i].value - << " for attribute type " << required_attribs[i].type; - return false; - } + if (!(attrib.value & VA_RT_FORMAT_YUV420)) { + DVLOG(1) << "YUV420 not supported by this VAAPI implementation"; + return false; } TryToSetVADisplayAttributeToLocalGPU(); - va_res = vaCreateConfig(va_display_, - va_profile, - entrypoint, - &required_attribs[0], - required_attribs.size(), - &va_config_id_); + va_res = vaCreateConfig(va_display_, va_profile, kEntrypoint, + &attrib, 1, &va_config_id_); VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); return true; @@ -369,7 +299,6 @@ bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, switch (va_buffer_type) { case VASliceParameterBufferType: case VASliceDataBufferType: - case VAEncSliceParameterBufferType: pending_slice_bufs_.push_back(buffer_id); break; @@ -381,43 +310,6 @@ bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, return true; } -bool VaapiWrapper::SubmitVAEncMiscParamBuffer( - VAEncMiscParameterType misc_param_type, - size_t size, - void* buffer) { - base::AutoLock auto_lock(va_lock_); - - VABufferID buffer_id; - VAStatus va_res = vaCreateBuffer(va_display_, - va_context_id_, - VAEncMiscParameterBufferType, - sizeof(VAEncMiscParameterBuffer) + size, - 1, - NULL, - &buffer_id); - VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); - - void* data_ptr = NULL; - va_res = vaMapBuffer(va_display_, buffer_id, &data_ptr); - VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); - if (va_res != VA_STATUS_SUCCESS) { - vaDestroyBuffer(va_display_, buffer_id); - return false; - } - - DCHECK(data_ptr); - - VAEncMiscParameterBuffer* misc_param = - reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr); - misc_param->type = misc_param_type; - memcpy(misc_param->data, buffer, size); - va_res = vaUnmapBuffer(va_display_, buffer_id); - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); - - pending_va_bufs_.push_back(buffer_id); - return true; -} - void VaapiWrapper::DestroyPendingBuffers() { base::AutoLock auto_lock(va_lock_); @@ -435,73 +327,38 @@ void VaapiWrapper::DestroyPendingBuffers() { pending_slice_bufs_.clear(); } -bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { - base::AutoLock auto_lock(va_lock_); - VAStatus va_res = vaCreateBuffer(va_display_, - va_context_id_, - VAEncCodedBufferType, - size, - 1, - NULL, - buffer_id); - VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false); - - DCHECK(coded_buffers_.insert(*buffer_id).second); - return true; -} - -void VaapiWrapper::DestroyCodedBuffers() { - base::AutoLock auto_lock(va_lock_); - - for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin(); - iter != coded_buffers_.end(); - ++iter) { - VAStatus va_res = vaDestroyBuffer(va_display_, *iter); - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); - } - - coded_buffers_.clear(); -} - -bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { +bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_id) { base::AutoLock auto_lock(va_lock_); DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); - DVLOG(4) << "Target VA surface " << va_surface_id; + DVLOG(4) << "Decoding into VA surface " << va_surface_id; - // Get ready to execute for given surface. + // Get ready to decode into surface. VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, va_surface_id); VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); - if (pending_va_bufs_.size() > 0) { - // Commit parameter and slice buffers. - va_res = vaRenderPicture(va_display_, - va_context_id_, - &pending_va_bufs_[0], - pending_va_bufs_.size()); - VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); - } + // Commit parameter and slice buffers. + va_res = vaRenderPicture(va_display_, va_context_id_, + &pending_va_bufs_[0], pending_va_bufs_.size()); + VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); - if (pending_slice_bufs_.size() > 0) { - va_res = vaRenderPicture(va_display_, - va_context_id_, - &pending_slice_bufs_[0], - pending_slice_bufs_.size()); - VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); - } + va_res = vaRenderPicture(va_display_, va_context_id_, + &pending_slice_bufs_[0], + pending_slice_bufs_.size()); + VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); - // Instruct HW codec to start processing committed buffers. - // Does not block and the job is not finished after this returns. + // Instruct HW decoder to start processing committed buffers (decode this + // picture). This does not block until the end of decode. va_res = vaEndPicture(va_display_, va_context_id_); VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); return true; } -bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { - bool result = Execute(va_surface_id); +bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) { + bool result = SubmitDecode(va_surface_id); DestroyPendingBuffers(); return result; } @@ -521,7 +378,8 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, 0, 0, dest_size.width(), dest_size.height(), 0, 0, dest_size.width(), dest_size.height(), NULL, 0, 0); - VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); + VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap", + false); return true; } @@ -545,124 +403,15 @@ bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, if (va_res == VA_STATUS_SUCCESS) return true; - va_res = vaDestroyImage(va_display_, image->image_id); - VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); - + vaDestroyImage(va_display_, image->image_id); return false; } void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { base::AutoLock auto_lock(va_lock_); - VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); - - va_res = vaDestroyImage(va_display_, image->image_id); - VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); -} - -static void DestroyVAImage(VADisplay va_display, VAImage image) { - if (image.image_id != VA_INVALID_ID) - vaDestroyImage(va_display, image.image_id); -} - -bool VaapiWrapper::UploadVideoFrameToSurface( - const scoped_refptr<media::VideoFrame>& frame, - VASurfaceID va_surface_id) { - base::AutoLock auto_lock(va_lock_); - - VAImage image; - VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); - VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); - base::ScopedClosureRunner vaimage_deleter( - base::Bind(&DestroyVAImage, va_display_, image)); - - if (image.format.fourcc != VA_FOURCC_NV12) { - DVLOG(1) << "Unsupported image format: " << image.format.fourcc; - return false; - } - - if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { - DVLOG(1) << "Buffer too small to fit the frame."; - return false; - } - - void* image_ptr = NULL; - va_res = vaMapBuffer(va_display_, image.buf, &image_ptr); - VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); - DCHECK(image_ptr); - - int ret = 0; - { - base::AutoUnlock auto_unlock(va_lock_); - ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kYPlane), - frame->data(media::VideoFrame::kUPlane), - frame->stride(media::VideoFrame::kUPlane), - frame->data(media::VideoFrame::kVPlane), - frame->stride(media::VideoFrame::kVPlane), - static_cast<uint8*>(image_ptr) + image.offsets[0], - image.pitches[0], - static_cast<uint8*>(image_ptr) + image.offsets[1], - image.pitches[1], - image.width, - image.height); - } - - va_res = vaUnmapBuffer(va_display_, image.buf); - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); - - return ret == 0; -} - -bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, - VASurfaceID sync_surface_id, - uint8* target_ptr, - size_t target_size, - size_t* coded_data_size) { - base::AutoLock auto_lock(va_lock_); - - VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id); - VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); - - VACodedBufferSegment* buffer_segment = NULL; - va_res = vaMapBuffer( - va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment)); - VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); - DCHECK(target_ptr); - - { - base::AutoUnlock auto_unlock(va_lock_); - *coded_data_size = 0; - - while (buffer_segment) { - DCHECK(buffer_segment->buf); - - if (buffer_segment->size > target_size) { - DVLOG(1) << "Insufficient output buffer size"; - break; - } - - memcpy(target_ptr, buffer_segment->buf, buffer_segment->size); - - target_ptr += buffer_segment->size; - *coded_data_size += buffer_segment->size; - target_size -= buffer_segment->size; - - buffer_segment = - reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next); - } - } - - va_res = vaUnmapBuffer(va_display_, buffer_id); - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); - - va_res = vaDestroyBuffer(va_display_, buffer_id); - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); - - DCHECK(coded_buffers_.erase(buffer_id)); - - return buffer_segment == NULL; + vaUnmapBuffer(va_display_, image->buf); + vaDestroyImage(va_display_, image->image_id); } // static diff --git a/content/common/gpu/media/vaapi_wrapper.h b/content/common/gpu/media/vaapi_wrapper.h index f600cdf..5570360 100644 --- a/content/common/gpu/media/vaapi_wrapper.h +++ b/content/common/gpu/media/vaapi_wrapper.h @@ -3,16 +3,12 @@ // found in the LICENSE file. // // This file contains an implementation of VaapiWrapper, used by -// VaapiVideoDecodeAccelerator and VaapiH264Decoder for decode, -// and VaapiVideoEncodeAccelerator for encode, to interface -// with libva (VA-API library for hardware video codec). +// VaapiVideoDecodeAccelerator and VaapiH264Decoder to interface +// with libva (VA-API library for hardware video decode). #ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_ #define CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_ -#include <set> -#include <vector> - #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" @@ -26,26 +22,20 @@ namespace content { // This class handles VA-API calls and ensures proper locking of VA-API calls -// to libva, the userspace shim to the HW codec driver. libva is not +// to libva, the userspace shim to the HW decoder driver. libva is not // thread-safe, so we have to perform locking ourselves. This class is fully // synchronous and its methods can be called from any thread and may wait on // the va_lock_ while other, concurrent calls run. // // This class is responsible for managing VAAPI connection, contexts and state. // It is also responsible for managing and freeing VABuffers (not VASurfaces), -// which are used to queue parameters and slice data to the HW codec, +// which are used to queue decode parameters and slice data to the HW decoder, // as well as underlying memory for VASurfaces themselves. class CONTENT_EXPORT VaapiWrapper { public: - enum CodecMode { - kDecode, - kEncode, - }; - // |report_error_to_uma_cb| will be called independently from reporting // errors to clients via method return values. static scoped_ptr<VaapiWrapper> Create( - CodecMode mode, media::VideoCodecProfile profile, Display* x_display, const base::Closure& report_error_to_uma_cb); @@ -67,30 +57,20 @@ class CONTENT_EXPORT VaapiWrapper { void DestroySurfaces(); // Submit parameters or slice data of |va_buffer_type|, copying them from - // |buffer| of size |size|, into HW codec. The data in |buffer| is no + // |buffer| of size |size|, into HW decoder. The data in |buffer| is no // longer needed and can be freed after this method returns. - // Data submitted via this method awaits in the HW codec until - // ExecuteAndDestroyPendingBuffers() is called to execute or - // DestroyPendingBuffers() is used to cancel a pending job. + // Data submitted via this method awaits in the HW decoder until + // DecodeAndDestroyPendingBuffers is called to execute or + // DestroyPendingBuffers is used to cancel a pending decode. bool SubmitBuffer(VABufferType va_buffer_type, size_t size, void* buffer); - // Submit a VAEncMiscParameterBuffer of given |misc_param_type|, copying its - // data from |buffer| of size |size|, into HW codec. The data in |buffer| is - // no longer needed and can be freed after this method returns. - // Data submitted via this method awaits in the HW codec until - // ExecuteAndDestroyPendingBuffers() is called to execute or - // DestroyPendingBuffers() is used to cancel a pending job. - bool SubmitVAEncMiscParamBuffer(VAEncMiscParameterType misc_param_type, - size_t size, - void* buffer); - - // Cancel and destroy all buffers queued to the HW codec via SubmitBuffer(). - // Useful when a pending job is to be cancelled (on reset or error). + // Cancel and destroy all buffers queued to the HW decoder via SubmitBuffer. + // Useful when a pending decode is to be cancelled (on reset or error). void DestroyPendingBuffers(); - // Execute job in hardware on target |va_surface_id| and destroy pending - // buffers. Return false if Execute() fails. - bool ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id); + // Execute decode in hardware into |va_surface_id} and destroy pending + // buffers. Return false if SubmitDecode() fails. + bool DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id); // Put data from |va_surface_id| into |x_pixmap| of size |size|, // converting/scaling to it. @@ -112,41 +92,18 @@ class CONTENT_EXPORT VaapiWrapper { // GetVaImage(). This is intended for testing only. void ReturnVaImageForTesting(VAImage* image); - // Upload contents of |frame| into |va_surface_id| for encode. - bool UploadVideoFrameToSurface(const scoped_refptr<media::VideoFrame>& frame, - VASurfaceID va_surface_id); - - // Create a buffer of |size| bytes to be used as encode output. - bool CreateCodedBuffer(size_t size, VABufferID* buffer_id); - - // Download the contents of the buffer with given |buffer_id| into a buffer of - // size |target_size|, pointed to by |target_ptr|. The number of bytes - // downloaded will be returned in |coded_data_size|. |sync_surface_id| will - // be used as a sync point, i.e. it will have to become idle before starting - // the download. |sync_surface_id| should be the source surface passed - // to the encode job. - bool DownloadAndDestroyCodedBuffer(VABufferID buffer_id, - VASurfaceID sync_surface_id, - uint8* target_ptr, - size_t target_size, - size_t* coded_data_size); - - // Destroy all previously-allocated (and not yet destroyed) coded buffers. - void DestroyCodedBuffers(); - private: VaapiWrapper(); - bool Initialize(CodecMode mode, - media::VideoCodecProfile profile, + bool Initialize(media::VideoCodecProfile profile, Display* x_display, const base::Closure& report_error__to_uma_cb); void Deinitialize(); - // Execute pending job in hardware and destroy pending buffers. Return false - // if vaapi driver refuses to accept parameter or slice buffers submitted - // by client, or if execution fails in hardware. - bool Execute(VASurfaceID va_surface_id); + // Execute decode in hardware and destroy pending buffers. Return false if + // vaapi driver refuses to accept parameter or slice buffers submitted + // by client or if decode fails in hardware. + bool SubmitDecode(VASurfaceID va_surface_id); // Attempt to set render mode to "render to texture.". Failure is non-fatal. void TryToSetVADisplayAttributeToLocalGPU(); @@ -157,7 +114,7 @@ class CONTENT_EXPORT VaapiWrapper { // Libva is not thread safe, so we have to do locking for it ourselves. // This lock is to be taken for the duration of all VA-API calls and for - // the entire job submission sequence in ExecuteAndDestroyPendingBuffers(). + // the entire decode execution sequence in DecodeAndDestroyPendingBuffers(). base::Lock va_lock_; // Allocated ids for VASurfaces. @@ -174,14 +131,11 @@ class CONTENT_EXPORT VaapiWrapper { // valid until DestroySurfaces(). VAContextID va_context_id_; - // Data queued up for HW codec, to be committed on next execution. + // Data queued up for HW decoder, to be committed on next HW decode. std::vector<VABufferID> pending_slice_bufs_; std::vector<VABufferID> pending_va_bufs_; - // Bitstream buffers for encode. - std::set<VABufferID> coded_buffers_; - - // Called to report codec errors to UMA. Errors to clients are reported via + // Called to report decoding errors to UMA. Errors to clients are reported via // return values from public methods. base::Closure report_error_to_uma_cb_; diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc index b07211d..5f60634 100644 --- a/content/common/gpu/media/video_encode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc @@ -13,6 +13,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/time/time.h" +#include "content/common/gpu/media/v4l2_video_encode_accelerator.h" #include "content/common/gpu/media/video_accelerator_unittest_helpers.h" #include "media/base/bind_to_current_loop.h" #include "media/base/bitstream_buffer.h" @@ -21,18 +22,6 @@ #include "media/video/video_encode_accelerator.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(USE_X11) -#include "ui/gfx/x/x11_types.h" -#endif - -#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) -#include "content/common/gpu/media/v4l2_video_encode_accelerator.h" -#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) -#include "content/common/gpu/media/vaapi_video_encode_accelerator.h" -#else -#error The VideoEncodeAcceleratorUnittest is not supported on this platform. -#endif - using media::VideoEncodeAccelerator; namespace content { @@ -255,29 +244,28 @@ class H264Validator : public StreamValidator { seen_pps_(false), seen_idr_(false) {} - virtual void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE; + void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE; private: // Set to true when encoder provides us with the corresponding NALU type. bool seen_sps_; bool seen_pps_; bool seen_idr_; - - media::H264Parser h264_parser_; }; void H264Validator::ProcessStreamBuffer(const uint8* stream, size_t size) { - h264_parser_.SetStream(stream, size); + media::H264Parser h264_parser; + h264_parser.SetStream(stream, size); while (1) { media::H264NALU nalu; media::H264Parser::Result result; - result = h264_parser_.AdvanceToNextNALU(&nalu); + result = h264_parser.AdvanceToNextNALU(&nalu); if (result == media::H264Parser::kEOStream) break; - ASSERT_EQ(media::H264Parser::kOk, result); + ASSERT_EQ(result, media::H264Parser::kOk); bool keyframe = false; @@ -285,35 +273,22 @@ void H264Validator::ProcessStreamBuffer(const uint8* stream, size_t size) { case media::H264NALU::kIDRSlice: ASSERT_TRUE(seen_sps_); ASSERT_TRUE(seen_pps_); - seen_idr_ = true; + seen_idr_ = keyframe = true; // fallthrough - case media::H264NALU::kNonIDRSlice: { + case media::H264NALU::kNonIDRSlice: ASSERT_TRUE(seen_idr_); - - media::H264SliceHeader shdr; - ASSERT_EQ(media::H264Parser::kOk, - h264_parser_.ParseSliceHeader(nalu, &shdr)); - keyframe = shdr.IsISlice() || shdr.IsSISlice(); - if (!frame_cb_.Run(keyframe)) return; break; - } - case media::H264NALU::kSPS: { - int sps_id; - ASSERT_EQ(media::H264Parser::kOk, h264_parser_.ParseSPS(&sps_id)); + case media::H264NALU::kSPS: seen_sps_ = true; break; - } - case media::H264NALU::kPPS: { + case media::H264NALU::kPPS: ASSERT_TRUE(seen_sps_); - int pps_id; - ASSERT_EQ(media::H264Parser::kOk, h264_parser_.ParsePPS(&pps_id)); seen_pps_ = true; break; - } default: break; @@ -327,7 +302,7 @@ class VP8Validator : public StreamValidator { : StreamValidator(frame_cb), seen_keyframe_(false) {} - virtual void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE; + void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE; private: // Have we already got a keyframe in the stream? @@ -382,13 +357,13 @@ class VEAClient : public VideoEncodeAccelerator::Client { double frames_per_second(); // VideoDecodeAccelerator::Client implementation. - virtual void RequireBitstreamBuffers(unsigned int input_count, - const gfx::Size& input_coded_size, - size_t output_buffer_size) OVERRIDE; - virtual void BitstreamBufferReady(int32 bitstream_buffer_id, - size_t payload_size, - bool key_frame) OVERRIDE; - virtual void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE; + void RequireBitstreamBuffers(unsigned int input_count, + const gfx::Size& input_coded_size, + size_t output_buffer_size) OVERRIDE; + void BitstreamBufferReady(int32 bitstream_buffer_id, + size_t payload_size, + bool key_frame) OVERRIDE; + void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE; private: bool has_encoder() { return encoder_.get(); } @@ -584,13 +559,8 @@ void VEAClient::CreateEncoder() { DCHECK(thread_checker_.CalledOnValidThread()); CHECK(!has_encoder()); -#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass())); -#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) - encoder_.reset(new VaapiVideoEncodeAccelerator(gfx::GetXDisplay())); -#endif - SetState(CS_ENCODER_SET); DVLOG(1) << "Profile: " << test_stream_.requested_profile diff --git a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc index 14eab49..d6b54f8 100644 --- a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc +++ b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc @@ -72,15 +72,9 @@ inline bool IsArchitectureArm() { #endif } -bool IsAcceleratedVideoEnabled() { +bool IsAcceleratedVideoDecodeEnabled() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - bool accelerated_encode_enabled = false; -#if defined(OS_CHROMEOS) - accelerated_encode_enabled = - command_line.HasSwitch(switches::kEnableVaapiAcceleratedVideoEncode); -#endif - return !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode) || - accelerated_encode_enabled; + return !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode); } intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args, @@ -220,9 +214,9 @@ bool GpuProcessPolicy::PreSandboxHook() { std::vector<std::string>()); if (IsArchitectureX86_64() || IsArchitectureI386()) { - // Accelerated video dlopen()'s some shared objects + // Accelerated video decode dlopen()'s some shared objects // inside the sandbox, so preload them now. - if (IsAcceleratedVideoEnabled()) { + if (IsAcceleratedVideoDecodeEnabled()) { const char* I965DrvVideoPath = NULL; if (IsArchitectureX86_64()) { diff --git a/content/content_common.gypi b/content/content_common.gypi index e773356..7bc6b8ce 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -717,10 +717,6 @@ ], }], ['target_arch != "arm" and chromeos == 1 and use_x11 == 1', { - 'dependencies': [ - '../media/media.gyp:media', - '../third_party/libyuv/libyuv.gyp:libyuv', - ], 'sources': [ 'common/gpu/media/h264_dpb.cc', 'common/gpu/media/h264_dpb.h', @@ -729,8 +725,6 @@ 'common/gpu/media/vaapi_h264_decoder.h', 'common/gpu/media/vaapi_video_decode_accelerator.cc', 'common/gpu/media/vaapi_video_decode_accelerator.h', - 'common/gpu/media/vaapi_video_encode_accelerator.cc', - 'common/gpu/media/vaapi_video_encode_accelerator.h', 'common/gpu/media/vaapi_wrapper.cc', 'common/gpu/media/vaapi_wrapper.h', ], @@ -746,7 +740,6 @@ }, 'include_dirs': [ '<(DEPTH)/third_party/libva', - '<(DEPTH)/third_party/libyuv', '<(output_root)', ], 'actions': [ diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 5dd398f..c33825d 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -1466,7 +1466,7 @@ }, ] }], - ['chromeos==1 and (target_arch == "arm" or use_x11 == 1)', { + ['chromeos==1 and target_arch == "arm"', { 'targets': [ { 'target_name': 'video_encode_accelerator_unittest', @@ -1486,17 +1486,6 @@ 'common/gpu/media/video_accelerator_unittest_helpers.h', 'common/gpu/media/video_encode_accelerator_unittest.cc', ], - 'include_dirs': [ - '<(DEPTH)/third_party/libva', - '<(DEPTH)/third_party/libyuv', - ], - 'conditions': [ - ['use_x11==1', { - 'dependencies': [ - '../ui/gfx/x/gfx_x11.gyp:gfx_x11', - ], - }], - ], }, ] }], diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 50d1998..0e946ef 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -926,10 +926,6 @@ const char kDisableWebAudio[] = "disable-webaudio"; #if defined(OS_CHROMEOS) // Disables panel fitting (used for mirror mode). const char kDisablePanelFitting[] = "disable-panel-fitting"; - -// Enables VA-API accelerated video encode. -const char kEnableVaapiAcceleratedVideoEncode[] = - "enable-vaapi-accelerated-video-encode"; #endif #if defined(OS_MACOSX) && !defined(OS_IOS) diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 798f495..9516dcf 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -267,7 +267,6 @@ CONTENT_EXPORT extern const char kDisableWebAudio[]; #if defined(OS_CHROMEOS) CONTENT_EXPORT extern const char kDisablePanelFitting[]; -CONTENT_EXPORT extern const char kEnableVaapiAcceleratedVideoEncode[]; #endif #if defined(OS_MACOSX) && !defined(OS_IOS) diff --git a/media/filters/h264_bitstream_buffer.cc b/media/filters/h264_bitstream_buffer.cc deleted file mode 100644 index 48463a5..0000000 --- a/media/filters/h264_bitstream_buffer.cc +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 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 "media/filters/h264_bitstream_buffer.h" - -#include "base/sys_byteorder.h" - -namespace media { - -H264BitstreamBuffer::H264BitstreamBuffer() : data_(NULL) { - Reset(); -} - -H264BitstreamBuffer::~H264BitstreamBuffer() { - free(data_); - data_ = NULL; -} - -void H264BitstreamBuffer::Reset() { - free(data_); - data_ = NULL; - - capacity_ = 0; - pos_ = 0; - reg_ = 0; - - Grow(); - - bits_left_in_reg_ = kRegBitSize; -} - -void H264BitstreamBuffer::Grow() { - data_ = static_cast<uint8*>(realloc(data_, capacity_ + kGrowBytes)); - CHECK(data_) << "Failed growing the buffer"; - capacity_ += kGrowBytes; -} - -void H264BitstreamBuffer::FlushReg() { - // Flush all bytes that have at least one bit cached, but not more - // (on Flush(), reg_ may not be full). - size_t bits_in_reg = kRegBitSize - bits_left_in_reg_; - if (bits_in_reg == 0) - return; - - size_t bytes_in_reg = (bits_in_reg + 7) / 8; - reg_ <<= (kRegBitSize - bits_in_reg); - - // Convert to MSB and append as such to the stream. - reg_ = base::HostToNet64(reg_); - - // Make sure we have enough space. Grow() will CHECK() on allocation failure. - if (pos_ + bytes_in_reg < capacity_) - Grow(); - - memcpy(data_ + pos_, ®_, bytes_in_reg); - pos_ += bytes_in_reg; - - reg_ = 0; - bits_left_in_reg_ = kRegBitSize; -} - -void H264BitstreamBuffer::AppendU64(size_t num_bits, uint64 val) { - CHECK_LE(num_bits, kRegBitSize); - - while (num_bits > 0) { - if (bits_left_in_reg_ == 0) - FlushReg(); - - uint64 bits_to_write = - num_bits > bits_left_in_reg_ ? bits_left_in_reg_ : num_bits; - uint64 val_to_write = (val >> (num_bits - bits_to_write)); - if (bits_to_write < 64) - val_to_write &= ((1ull << bits_to_write) - 1); - reg_ <<= bits_to_write; - reg_ |= val_to_write; - num_bits -= bits_to_write; - bits_left_in_reg_ -= bits_to_write; - } -} - -void H264BitstreamBuffer::AppendBool(bool val) { - if (bits_left_in_reg_ == 0) - FlushReg(); - - reg_ <<= 1; - reg_ |= (static_cast<uint64>(val) & 1); - --bits_left_in_reg_; -} - -void H264BitstreamBuffer::AppendSE(int val) { - if (val > 0) - AppendUE(val * 2 - 1); - else - AppendUE(-val * 2); -} - -void H264BitstreamBuffer::AppendUE(unsigned int val) { - size_t num_zeros = 0; - unsigned int v = val + 1; - - while (v > 1) { - v >>= 1; - ++num_zeros; - } - - AppendBits(num_zeros, 0); - AppendBits(num_zeros + 1, val + 1); -} - -#define DCHECK_FINISHED() \ - DCHECK_EQ(bits_left_in_reg_, kRegBitSize) << "Pending bits not yet written " \ - "to the buffer, call " \ - "FinishNALU() first." - -void H264BitstreamBuffer::BeginNALU(H264NALU::Type nalu_type, int nal_ref_idc) { - DCHECK_FINISHED(); - - DCHECK_LE(nalu_type, H264NALU::kEOStream); - DCHECK_GE(nal_ref_idc, 0); - DCHECK_LE(nal_ref_idc, 3); - - AppendBits(32, 0x00000001); - AppendBits(1, 0); // forbidden_zero_bit - AppendBits(2, nal_ref_idc); - AppendBits(5, nalu_type); -} - -void H264BitstreamBuffer::FinishNALU() { - // RBSP stop one bit. - AppendBits(1, 1); - - // Byte-alignment zero bits. - AppendBits(bits_left_in_reg_ % 8, 0); - - if (bits_left_in_reg_ != kRegBitSize) - FlushReg(); -} - -size_t H264BitstreamBuffer::BytesInBuffer() { - DCHECK_FINISHED(); - return pos_; -} - -uint8* H264BitstreamBuffer::data() { - DCHECK(data_); - DCHECK_FINISHED(); - - return data_; -} - -} // namespace media diff --git a/media/filters/h264_bitstream_buffer.h b/media/filters/h264_bitstream_buffer.h deleted file mode 100644 index 4b0511d..0000000 --- a/media/filters/h264_bitstream_buffer.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 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. -// -// This file contains an implementation of a H264BitstreamBuffer class for -// constructing raw bitstream buffers containing NAL units in -// H.264 Annex-B stream format. -// See H.264 spec Annex B and chapter 7for more details. - -#ifndef MEDIA_FILTERS_H264_BITSTREAM_BUFFER_H_ -#define MEDIA_FILTERS_H264_BITSTREAM_BUFFER_H_ - -#include "base/gtest_prod_util.h" -#include "base/numerics/safe_conversions.h" -#include "media/base/media_export.h" -#include "media/base/video_frame.h" -#include "media/filters/h264_parser.h" - -namespace media { - -// Holds one or more NALUs as a raw bitstream buffer in H.264 Annex-B format. -// Note that this class currently does NOT insert emulation prevention -// three-byte sequences (spec 7.3.1). -class MEDIA_EXPORT H264BitstreamBuffer { - public: - H264BitstreamBuffer(); - ~H264BitstreamBuffer(); - - // Discard all data and reset the buffer for reuse. - void Reset(); - - // Append |num_bits| bits to the stream from |val|. - // |val| is interpreted in the host endianness. - template <typename T> - void AppendBits(size_t num_bits, T val) { - AppendU64(num_bits, static_cast<uint64>(val)); - } - - void AppendBits(size_t num_bits, bool val) { - DCHECK_EQ(num_bits, 1ul); - AppendBool(val); - } - - // Append a one-bit bool/flag value |val| to the stream. - void AppendBool(bool val); - - // Append a signed value in |val| in Exp-Golomb code. - void AppendSE(int val); - - // Append an unsigned value in |val| in Exp-Golomb code. - void AppendUE(unsigned int val); - - // Start a new NALU of type |nalu_type| and with given |nal_ref_idc| - // (see spec). Note, that until FinishNALU() is called, some of the bits - // may not be flushed into the buffer and the data will not be correctly - // aligned with trailing bits. - void BeginNALU(H264NALU::Type nalu_type, int nal_ref_idc); - - // Finish current NALU. This will flush any cached bits and correctly align - // the buffer with RBSP trailing bits. This MUST be called for the stream - // returned by data() to be correct. - void FinishNALU(); - - // Return number of full bytes in the stream. Note that FinishNALU() has to - // be called to flush cached bits, or the return value will not include them. - size_t BytesInBuffer(); - - // Return a pointer to the stream. FinishNALU() must be called before - // accessing the stream, otherwise some bits may still be cached and not - // in the buffer. - uint8* data(); - - private: - FRIEND_TEST_ALL_PREFIXES(H264BitstreamBufferAppendBitsTest, - AppendAndVerifyBits); - - // Allocate additional memory (kGrowBytes bytes) for the buffer. - void Grow(); - - // Append |num_bits| bits from U64 value |val| (in host endianness). - void AppendU64(size_t num_bits, uint64 val); - - // Flush any cached bits in the reg with byte granularity, i.e. enough - // bytes to flush all pending bits, but not more. - void FlushReg(); - - typedef uint64 RegType; - enum { - // Sizes of reg_. - kRegByteSize = sizeof(RegType), - kRegBitSize = kRegByteSize * 8, - // Amount of bytes to grow the buffer by when we run out of - // previously-allocated memory for it. - kGrowBytes = 4096, - }; - - COMPILE_ASSERT(kGrowBytes >= kRegByteSize, - kGrowBytes_must_be_larger_than_kRegByteSize); - - // Unused bits left in reg_. - size_t bits_left_in_reg_; - - // Cache for appended bits. Bits are flushed to data_ with kRegByteSize - // granularity, i.e. when reg_ becomes full, or when an explicit FlushReg() - // is called. - RegType reg_; - - // Current capacity of data_, in bytes. - size_t capacity_; - - // Current byte offset in data_ (points to the start of unwritten bits). - size_t pos_; - - // Buffer for stream data. - uint8* data_; -}; - -} // namespace media - -#endif // MEDIA_FILTERS_H264_BITSTREAM_BUFFER_H_ diff --git a/media/filters/h264_bitstream_buffer_unittest.cc b/media/filters/h264_bitstream_buffer_unittest.cc deleted file mode 100644 index 3775829..0000000 --- a/media/filters/h264_bitstream_buffer_unittest.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 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 "media/filters/h264_bitstream_buffer.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -namespace { -const uint64 kTestPattern = 0xfedcba0987654321; -} - -class H264BitstreamBufferAppendBitsTest - : public ::testing::TestWithParam<size_t> {}; - -// TODO(posciak): More tests! - -TEST_P(H264BitstreamBufferAppendBitsTest, AppendAndVerifyBits) { - H264BitstreamBuffer b; - uint64 num_bits = GetParam(); - // TODO(posciak): Tests for >64 bits. - ASSERT_LE(num_bits, 64u); - uint64 num_bytes = (num_bits + 7) / 8; - - b.AppendBits(num_bits, kTestPattern); - b.FlushReg(); - - EXPECT_EQ(b.BytesInBuffer(), num_bytes); - - uint8* ptr = b.data(); - uint64 got = 0; - uint64 expected = kTestPattern; - - if (num_bits < 64) - expected &= ((1ull << num_bits) - 1); - - while (num_bits > 8) { - got |= (*ptr & 0xff); - num_bits -= 8; - got <<= (num_bits > 8 ? 8 : num_bits); - ptr++; - } - if (num_bits > 0) { - uint64 temp = (*ptr & 0xff); - temp >>= (8 - num_bits); - got |= temp; - } - EXPECT_EQ(got, expected) << std::hex << "0x" << got << " vs 0x" << expected; -} - -INSTANTIATE_TEST_CASE_P(AppendNumBits, - H264BitstreamBufferAppendBitsTest, - ::testing::Range(1ul, 65ul)); -} // namespace media diff --git a/media/filters/h264_parser.cc b/media/filters/h264_parser.cc index ee21ab8..4cdc695 100644 --- a/media/filters/h264_parser.cc +++ b/media/filters/h264_parser.cc @@ -106,6 +106,10 @@ H264SEIMessage::H264SEIMessage() { } \ } while (0) +enum AspectRatioIdc { + kExtendedSar = 255, +}; + // ISO 14496 part 10 // VUI parameters: Table E-1 "Meaning of sample aspect ratio indicator" static const int kTableSarWidth[] = { @@ -604,7 +608,7 @@ H264Parser::Result H264Parser::ParseVUIParameters(H264SPS* sps) { if (aspect_ratio_info_present_flag) { int aspect_ratio_idc; READ_BITS_OR_RETURN(8, &aspect_ratio_idc); - if (aspect_ratio_idc == H264SPS::kExtendedSar) { + if (aspect_ratio_idc == kExtendedSar) { READ_BITS_OR_RETURN(16, &sps->sar_width); READ_BITS_OR_RETURN(16, &sps->sar_height); } else { diff --git a/media/filters/h264_parser.h b/media/filters/h264_parser.h index 45020af..3a60dce 100644 --- a/media/filters/h264_parser.h +++ b/media/filters/h264_parser.h @@ -63,26 +63,6 @@ enum { struct MEDIA_EXPORT H264SPS { H264SPS(); - enum H264ProfileIDC { - kProfileIDCBaseline = 66, - kProfileIDCConstrainedBaseline = kProfileIDCBaseline, - kProfileIDCMain = 77, - kProfileIDCHigh = 100, - }; - - enum AspectRatioIdc { - kExtendedSar = 255, - }; - - enum { - // Constants for HRD parameters (spec ch. E.2.2). - kBitRateScaleConstantTerm = 6, // Equation E-37. - kCPBSizeScaleConstantTerm = 4, // Equation E-38. - kDefaultInitialCPBRemovalDelayLength = 24, - kDefaultDPBOutputDelayLength = 24, - kDefaultTimeOffsetLength = 24, - }; - int profile_idc; bool constraint_set0_flag; bool constraint_set1_flag; @@ -131,25 +111,6 @@ struct MEDIA_EXPORT H264SPS { bool bitstream_restriction_flag; int max_num_reorder_frames; int max_dec_frame_buffering; - bool timing_info_present_flag; - int num_units_in_tick; - int time_scale; - bool fixed_frame_rate_flag; - - // TODO(posciak): actually parse these instead of ParseAndIgnoreHRDParameters. - bool nal_hrd_parameters_present_flag; - int cpb_cnt_minus1; - int bit_rate_scale; - int cpb_size_scale; - int bit_rate_value_minus1[32]; - int cpb_size_value_minus1[32]; - bool cbr_flag[32]; - int initial_cpb_removal_delay_length_minus_1; - int cpb_removal_delay_length_minus1; - int dpb_output_delay_length_minus1; - int time_offset_length; - - bool low_delay_hrd_flag; int chroma_array_type; }; diff --git a/media/media.gyp b/media/media.gyp index 1b3987a..7a38a4f 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -659,13 +659,6 @@ 'formats/webm/chromeos/webm_encoder.h', ], }], - # For VaapiVideoEncodeAccelerator. - ['target_arch != "arm" and chromeos == 1 and use_x11 == 1', { - 'sources': [ - 'filters/h264_bitstream_buffer.cc', - 'filters/h264_bitstream_buffer.h', - ], - }], ['OS!="ios"', { 'dependencies': [ '../third_party/libyuv/libyuv.gyp:libyuv', @@ -1230,11 +1223,6 @@ }], ], }], - ['target_arch != "arm" and chromeos == 1 and use_x11 == 1', { - 'sources': [ - 'filters/h264_bitstream_buffer_unittest.cc', - ], - }], ['use_alsa==0', { 'sources!': [ 'audio/alsa/alsa_output_unittest.cc', diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 83bfed0..386f597 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -10312,13 +10312,6 @@ Therefore, the affected-histogram name has to have at least one dot in it. </summary> </histogram> -<histogram name="Media.VAVEA.EncoderFailure" enum="VAVEAEncoderFailure"> - <owner>posciak@chromium.org</owner> - <summary> - Error codes reported by video encode using VA-API hardware video encoder. - </summary> -</histogram> - <histogram name="Media.VideoCapture.AspectRatio"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> @@ -46490,10 +46483,6 @@ Therefore, the affected-histogram name has to have at least one dot in it. <int value="4" label="VAAPI_ERROR"/> </enum> -<enum name="VAVEAEncoderFailure" type="int"> - <int value="0" label="VAAPI_ERROR"/> -</enum> - <enum name="VideoCodec" type="int"> <int value="0" label="kUnknownVideoCodec"/> <int value="1" label="kCodecH264"/> |