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

Unified Diff: content/common/gpu/media/vaapi_video_decode_accelerator.cc

Issue 14914009: VAVDA: Redesign stage 1. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/media/vaapi_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index a401ef64ab3eef04fa67fc7660aaf0995859364d..719d199dc84b7224d2c3c4d8c2c3251c7edd577b 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -3,20 +3,30 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/string_util.h"
#include "base/synchronization/waitable_event.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
-#include "content/public/common/content_switches.h"
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
#include "media/base/bind_to_loop.h"
#include "media/video/picture.h"
-#include "third_party/libva/va/va.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/scoped_binders.h"
+
+namespace {
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 pointless
Pawel Osciak 2013/05/21 22:32:35 Even if at some point a global ReportToUMA() surfa
Ami GONE FROM CHROMIUM 2013/05/22 23:59:47 Anything global in the future should be namespaced
Pawel Osciak 2013/05/24 01:46:39 Done.
+
+static void ReportToUMA(
+ content::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VAVDAH264.DecoderFailure",
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 This is clearly a decoder thing, not a VAVDA thing
Pawel Osciak 2013/05/21 22:32:35 Yeah, I hate it too, but didn't see a better way t
+ failure,
+ content::VaapiH264Decoder::VAVDA_H264_DECODER_FAILURES_MAX);
+}
+
+} // namespace
namespace content {
@@ -54,6 +64,175 @@ void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
}
}
+class VaapiVideoDecodeAccelerator::TFPPicture {
+ public:
+ ~TFPPicture();
+
+ static linked_ptr<TFPPicture> Create(
+ const base::Callback<bool(void)>& make_context_current,
+ const GLXFBConfig& fb_config,
+ Display* x_display,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ int width, int height);
+
+ int32 picture_buffer_id() {
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 Please rationalize order of ctor args, getters, an
Pawel Osciak 2013/05/21 22:32:35 Not really anything in particular, but getters are
+ return picture_buffer_id_;
+ }
+
+ uint32 texture_id() {
+ return texture_id_;
+ }
+
+ int width() {
+ return width_;
+ }
+
+ int height() {
+ return height_;
+ }
+
+ int x_pixmap() {
+ return x_pixmap_;
+ }
+
+ // Bind texture to pixmap. Needs to be called every frame.
+ bool Bind();
+
+ private:
+ TFPPicture(const base::Callback<bool(void)>& make_context_current,
+ Display* x_display,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ int width, int height);
+
+ bool Initialize(const GLXFBConfig& fb_config);
+
+ base::Callback<bool(void)> make_context_current_;
+
+ // Output id for the client.
+ int32 picture_buffer_id_;
+ uint32 texture_id_;
+
+ int width_;
+ int height_;
+
+ Display* x_display_;
+
+ // Pixmaps bound to this texture.
+ Pixmap x_pixmap_;
+ GLXPixmap glx_pixmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(TFPPicture);
+};
+
+VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
+ const base::Callback<bool(void)>& make_context_current,
+ Display* x_display,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ int width, int height)
+ : make_context_current_(make_context_current),
+ picture_buffer_id_(picture_buffer_id),
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 indent here and below
Pawel Osciak 2013/05/21 22:32:35 Done.
+ texture_id_(texture_id),
+ width_(width),
+ height_(height),
+ x_display_(x_display),
+ x_pixmap_(0),
+ glx_pixmap_(0) {
+ DCHECK(!make_context_current_.is_null());
+};
+
+linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
+VaapiVideoDecodeAccelerator::TFPPicture::Create(
+ const base::Callback<bool(void)>& make_context_current,
+ const GLXFBConfig& fb_config,
+ Display* x_display,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ int width, int height) {
+
+ linked_ptr<TFPPicture> tfp_picture(
+ new TFPPicture(make_context_current, x_display, picture_buffer_id,
+ texture_id, width, height));
+
+ if (!tfp_picture->Initialize(fb_config))
+ tfp_picture.reset();
+
+ return tfp_picture;
+}
+
+bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
+ const GLXFBConfig& fb_config) {
+ if (!make_context_current_.Run())
+ return false;
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ XWindowAttributes win_attr;
+ int screen = DefaultScreen(x_display_);
+ XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
+ //TODO(posciak): pass the depth required by libva, not the RootWindow's depth
+ x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
+ width_, height_, win_attr.depth);
+ if (!x_pixmap_) {
+ DVLOG(1) << "Failed creating an X Pixmap for TFP";
+ return NULL;
+ }
+
+ static const int pixmap_attr[] = {
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+ GL_NONE,
+ };
+
+ glx_pixmap_ = glXCreatePixmap(x_display_, fb_config, x_pixmap_, pixmap_attr);
+ if (!glx_pixmap_) {
+ // x_pixmap_ will be freed in the destructor.
+ DVLOG(1) << "Failed creating a GLX Pixmap for TFP";
+ return NULL;
+ }
+
+ return true;
+}
+
+VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
+ // Unbind surface from texture and deallocate resources.
+ if (glx_pixmap_ && make_context_current_.Run()) {
+ glXReleaseTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
+ glXDestroyPixmap(x_display_, glx_pixmap_);
+ }
+
+ if (x_pixmap_)
+ XFreePixmap(x_display_, x_pixmap_);
+ XSync(x_display_, False); // Needed to work around buggy vdpau-driver.
+}
+
+bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
+ DCHECK(x_pixmap_);
+ DCHECK(glx_pixmap_);
+
+ if (!make_context_current_.Run())
+ return false;
+
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 Is it really correct to have this be scoped to jus
Pawel Osciak 2013/05/21 22:32:35 No. This saves the texture that was bound (current
+ glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
+
+ return true;
+}
+
+VaapiVideoDecodeAccelerator::TFPPicture*
+ VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
+ TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
+ if (it == tfp_pictures_.end()) {
+ DVLOG(1) << "Picture id " << picture_buffer_id << " does not exist";
+ return NULL;
+ }
+
+ return it->second.get();
+}
+
VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
Display* x_display, GLXContext glx_context,
Client* client,
@@ -63,7 +242,7 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
make_context_current_(make_context_current),
state_(kUninitialized),
input_ready_(&lock_),
- output_ready_(&lock_),
+ surfaces_available_(&lock_),
message_loop_(base::MessageLoop::current()),
weak_this_(base::AsWeakPtr(this)),
client_ptr_factory_(client),
@@ -72,16 +251,41 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
num_frames_at_client_(0),
num_stream_bufs_at_decoder_(0) {
DCHECK(client);
- static bool vaapi_functions_initialized = PostSandboxInitialization();
- RETURN_AND_NOTIFY_ON_FAILURE(vaapi_functions_initialized,
- "Failed to initialize VAAPI libs",
- PLATFORM_FAILURE, );
}
VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
}
+class ScopedPtrXFree {
+ public:
+ void operator()(void* x) const {
+ ::XFree(x);
+ }
+};
+
+bool VaapiVideoDecodeAccelerator::InitializeFBConfig() {
+ const int fbconfig_attr[] = {
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+ GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
+ GLX_Y_INVERTED_EXT, GL_TRUE,
+ GL_NONE,
+ };
+
+ int num_fbconfigs;
+ scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> glx_fb_configs(
+ glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr,
+ &num_fbconfigs));
+ if (!glx_fb_configs)
+ return false;
+ if (!num_fbconfigs)
+ return false;
+
+ fb_config_ = glx_fb_configs.get()[0];
+ return true;
+}
+
bool VaapiVideoDecodeAccelerator::Initialize(
media::VideoCodecProfile profile) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
@@ -90,17 +294,30 @@ bool VaapiVideoDecodeAccelerator::Initialize(
DCHECK_EQ(state_, kUninitialized);
DVLOG(2) << "Initializing VAVDA, profile: " << profile;
- bool res = decoder_.Initialize(
- profile, x_display_, glx_context_, make_context_current_,
- media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind(
- &VaapiVideoDecodeAccelerator::NotifyPictureReady, weak_this_)),
- media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind(
- &VaapiVideoDecodeAccelerator::SubmitDecode, weak_this_)));
- if (!res) {
- DVLOG(1) << "Failed initializing decoder";
+ if (!make_context_current_.Run())
+ return false;
+
+ if (!InitializeFBConfig()) {
+ DVLOG(1) << "Could not get a usable FBConfig";
return false;
}
+ vaapi_delegate_ = VaapiDelegate::Create(
+ profile, x_display_,
+ base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR));
+
+ if (!vaapi_delegate_.get()) {
+ DVLOG(1) << "Failed initializing VAAPI";
+ return false;
+ }
+
+ decoder_.reset(
+ new VaapiH264Decoder(
+ vaapi_delegate_,
+ media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind(
+ &VaapiVideoDecodeAccelerator::SurfaceReady, weak_this_)),
+ base::Bind(&ReportToUMA)));
+
CHECK(decoder_thread_.Start());
state_ = kInitialized;
@@ -110,55 +327,84 @@ bool VaapiVideoDecodeAccelerator::Initialize(
return true;
}
-void VaapiVideoDecodeAccelerator::SubmitDecode(
- int32 output_id,
- scoped_ptr<std::queue<VABufferID> > va_bufs,
- scoped_ptr<std::queue<VABufferID> > slice_bufs) {
+void VaapiVideoDecodeAccelerator::SyncSurfaceToPicture(
+ VASurfaceID va_surface_id,
+ TFPPicture* tfp_picture) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
- base::AutoLock auto_lock(lock_);
-
- TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "output_id", output_id);
- // Handle Destroy() arriving while pictures are queued for output.
- if (!client_)
- return;
+ RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Bind(),
+ "Failed binding texture to pixmap",
+ PLATFORM_FAILURE, );
RETURN_AND_NOTIFY_ON_FAILURE(
- decoder_.SubmitDecode(output_id, va_bufs.Pass(), slice_bufs.Pass()),
- "Failed putting picture to texture",
- PLATFORM_FAILURE, );
+ vaapi_delegate_->PutSurfaceIntoPixmap(va_surface_id,
+ tfp_picture->x_pixmap(),
+ tfp_picture->width(),
+ tfp_picture->height()),
+ "Failed putting surface into pixmap", PLATFORM_FAILURE, );
}
-void VaapiVideoDecodeAccelerator::NotifyPictureReady(int32 input_id,
- int32 output_id) {
+void VaapiVideoDecodeAccelerator::SurfaceReady(
+ int32 input_id,
+ const scoped_refptr<VASurface>& va_surface) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
- TRACE_EVENT2("Video Decoder", "VAVDA::NotifyPictureReady",
- "input_id", input_id, "output_id", output_id);
- // Handle Destroy() arriving while pictures are queued for output.
- if (!client_)
+ // Drop any requests to output if we are resetting.
+ if (state_ == kResetting || state_ == kDestroying)
return;
- // Don't return any pictures that we might want to return during resetting
- // as a consequence of finishing up the decode that was running during
- // Reset() call from the client. Reuse it instead.
- {
- base::AutoLock auto_lock(lock_);
- if (state_ == kResetting) {
- output_buffers_.push(output_id);
- return;
- }
- }
+ pending_output_cbs_.push(
+ base::Bind(&VaapiVideoDecodeAccelerator::OutputPicture,
+ weak_this_, va_surface, input_id));
- ++num_frames_at_client_;
- TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
+ TryOutputSurface();
+}
+
+void VaapiVideoDecodeAccelerator::OutputPicture(
+ const scoped_refptr<VASurface>& va_surface,
+ int32 input_id,
+ TFPPicture* tfp_picture) {
+ DCHECK_EQ(message_loop_, base::MessageLoop::current());
+
+ int32 output_id = tfp_picture->picture_buffer_id();
+
+ TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface",
+ "input_id", input_id,
+ "output_id", output_id);
+
+ DVLOG(3) << "Outputting VASurface " << va_surface->id()
+ << " into pixmap bound to picture buffer id " << output_id;
+
+ SyncSurfaceToPicture(va_surface->id(), tfp_picture);
// Notify the client a picture is ready to be displayed.
+ ++num_frames_at_client_;
+ TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
DVLOG(4) << "Notifying output picture id " << output_id
<< " for input "<< input_id << " is ready";
client_->PictureReady(media::Picture(output_id, input_id));
}
+void VaapiVideoDecodeAccelerator::TryOutputSurface() {
+ DCHECK_EQ(message_loop_, base::MessageLoop::current());
+
+ // Handle Destroy() arriving while pictures are queued for output.
+ if (!client_)
+ return;
+
+ if (pending_output_cbs_.empty() || output_buffers_.empty())
+ return;
+
+ OutputCB output_cb = pending_output_cbs_.front();
+ pending_output_cbs_.pop();
+
+ TFPPicture* tfp_picture = TFPPictureById(output_buffers_.front());
+ DCHECK(tfp_picture);
+ output_buffers_.pop();
+
+ output_cb.Run(tfp_picture);
+}
+
void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
const media::BitstreamBuffer& bitstream_buffer) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
@@ -205,18 +451,18 @@ void VaapiVideoDecodeAccelerator::InitialDecodeTask() {
return;
VaapiH264Decoder::DecResult res =
- decoder_.DecodeInitial(curr_input_buffer_->id);
+ decoder_->DecodeInitial(curr_input_buffer_->id);
switch (res) {
case VaapiH264Decoder::kReadyToDecode:
if (state_ == kInitialized) {
state_ = kPicturesRequested;
- size_t num_pics = decoder_.GetRequiredNumOfPictures();
- gfx::Size size(decoder_.pic_width(), decoder_.pic_height());
- DVLOG(1) << "Requesting " << num_pics << " pictures of size: "
- << size.width() << "x" << size.height();
+ num_pics_ = decoder_->GetRequiredNumOfPictures();
+ pic_size_ = decoder_->GetPicSize();
+ DVLOG(1) << "Requesting " << num_pics_ << " pictures of size: "
+ << pic_size_.width() << "x" << pic_size_.height();
message_loop_->PostTask(FROM_HERE, base::Bind(
&Client::ProvidePictureBuffers, client_,
- num_pics, size, GL_TEXTURE_2D));
+ num_pics_, pic_size_, GL_TEXTURE_2D));
} else {
DCHECK_EQ(state_, kIdle);
state_ = kDecoding;
@@ -234,7 +480,7 @@ void VaapiVideoDecodeAccelerator::InitialDecodeTask() {
if (state_ == kIdle) {
// No more output buffers in the decoder, try getting more or go to
// sleep waiting for them.
- GetOutputBuffers_Locked();
+ GetOutputSurfaces_Locked();
return;
}
// else fallthrough
@@ -285,7 +531,7 @@ bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
<< curr_input_buffer_->id
<< " size: " << curr_input_buffer_->size;
- decoder_.SetStream(
+ decoder_->SetStream(
static_cast<uint8*>(curr_input_buffer_->shm->memory()),
curr_input_buffer_->size);
return true;
@@ -313,21 +559,27 @@ void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
num_stream_bufs_at_decoder_);
}
-bool VaapiVideoDecodeAccelerator::GetOutputBuffers_Locked() {
+bool VaapiVideoDecodeAccelerator::GetOutputSurfaces_Locked() {
lock_.AssertAcquired();
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
- while (output_buffers_.empty() &&
+ while (available_va_surfaces_.empty() &&
(state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
- output_ready_.Wait();
+ surfaces_available_.Wait();
}
if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle)
return false;
- while (!output_buffers_.empty()) {
- decoder_.ReusePictureBuffer(output_buffers_.front());
- output_buffers_.pop();
+ VASurface::ReleaseCB va_surface_relase_cb =
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 typo: va_surface_relase_cb
Pawel Osciak 2013/05/21 22:32:35 Done.
+ media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind(
+ &VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_));
+
+ while (!available_va_surfaces_.empty()) {
+ scoped_refptr<VASurface> va_surface(
+ new VASurface(available_va_surfaces_.front(), va_surface_relase_cb));
+ available_va_surfaces_.pop_front();
+ decoder_->ReuseSurface(va_surface);
}
return true;
@@ -347,21 +599,20 @@ void VaapiVideoDecodeAccelerator::DecodeTask() {
DCHECK(curr_input_buffer_.get());
VaapiH264Decoder::DecResult res;
- res = decoder_.DecodeOneFrame(curr_input_buffer_->id);
+ {
+ base::AutoUnlock auto_unlock(lock_);
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 Comment about why and why safe.
Pawel Osciak 2013/05/21 22:32:35 Done.
+ res = decoder_->DecodeOneFrame(curr_input_buffer_->id);
+ }
switch (res) {
case VaapiH264Decoder::kNeedMoreStreamData:
ReturnCurrInputBuffer_Locked();
break;
- case VaapiH264Decoder::kDecodedFrame:
- // May still have more stream data, continue decoding.
- break;
-
case VaapiH264Decoder::kNoOutputAvailable:
// No more output buffers in the decoder, try getting more or go to
// sleep waiting for them.
- if (!GetOutputBuffers_Locked())
+ if (!GetOutputSurfaces_Locked())
return;
break;
@@ -423,26 +674,58 @@ void VaapiVideoDecodeAccelerator::Decode(
}
}
+void VaapiVideoDecodeAccelerator::RecycleVASurfaceID(
+ VASurfaceID va_surface_id) {
+ DCHECK_EQ(message_loop_, base::MessageLoop::current());
+
+ base::AutoLock auto_lock(lock_);
+
+ available_va_surfaces_.push_back(va_surface_id);
+ surfaces_available_.Signal();
+}
+
void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
const std::vector<media::PictureBuffer>& buffers) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
base::AutoLock auto_lock(lock_);
DCHECK_EQ(state_, kPicturesRequested);
- size_t num_pics = decoder_.GetRequiredNumOfPictures();
- RETURN_AND_NOTIFY_ON_FAILURE((num_pics == buffers.size()),
- "Failed to provide requested picture buffers. (Got " << buffers.size() <<
- ", requested " << num_pics << ")", INVALID_ARGUMENT,);
+ DCHECK(tfp_pictures_.empty());
+
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ buffers.size() == num_pics_,
+ "Got an invalid number of picture buffers. (Got " << buffers.size()
+ << ", requested " << num_pics_ << ")", INVALID_ARGUMENT, );
+
+ std::vector<VASurfaceID> va_surface_ids;
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ vaapi_delegate_->CreateSurfaces(pic_size_.width(), pic_size_.height(),
+ buffers.size(),
+ va_surface_ids),
+ "Failed creating VA Surfaces", PLATFORM_FAILURE, );
+ DCHECK_EQ(va_surface_ids.size(), buffers.size());
for (size_t i = 0; i < buffers.size(); ++i) {
- DVLOG(2) << "Assigning picture id " << buffers[i].id()
- << " to texture id " << buffers[i].texture_id();
+ DVLOG(2) << "Assigning picture id: " << buffers[i].id()
+ << " to texture id: " << buffers[i].texture_id()
+ << " VASurfaceID: " << va_surface_ids[i];
+
+ linked_ptr<TFPPicture> tfp_picture(
+ TFPPicture::Create(make_context_current_, fb_config_, x_display_,
+ buffers[i].id(), buffers[i].texture_id(),
+ pic_size_.width(), pic_size_.height()));
- bool res = decoder_.AssignPictureBuffer(buffers[i].id(),
- buffers[i].texture_id());
RETURN_AND_NOTIFY_ON_FAILURE(
- res, "Failed assigning picture buffer id: " << buffers[i].id() <<
- ", texture id: " << buffers[i].texture_id(), PLATFORM_FAILURE, );
+ tfp_picture.get(), "Failed assigning picture buffer to a texture.",
+ PLATFORM_FAILURE, );
+
+ bool inserted = tfp_pictures_.insert(std::make_pair(
+ buffers[i].id(), tfp_picture)).second;
+ DCHECK(inserted);
+
+ output_buffers_.push(buffers[i].id());
+ available_va_surfaces_.push_back(va_surface_ids[i]);
+ surfaces_available_.Signal();
}
state_ = kDecoding;
@@ -458,25 +741,22 @@ void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
--num_frames_at_client_;
TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
- base::AutoLock auto_lock(lock_);
output_buffers_.push(picture_buffer_id);
- output_ready_.Signal();
+ TryOutputSurface();
}
void VaapiVideoDecodeAccelerator::FlushTask() {
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
DVLOG(1) << "Flush task";
- base::AutoLock auto_lock(lock_);
-
// First flush all the pictures that haven't been outputted, notifying the
// client to output them.
- bool res = decoder_.Flush();
+ bool res = decoder_->Flush();
RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.",
PLATFORM_FAILURE, );
// Put the decoder in idle state, ready to resume.
- decoder_.Reset();
+ decoder_->Reset();
message_loop_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
@@ -493,7 +773,7 @@ void VaapiVideoDecodeAccelerator::Flush() {
&VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
input_ready_.Signal();
- output_ready_.Signal();
+ surfaces_available_.Signal();
}
void VaapiVideoDecodeAccelerator::FinishFlush() {
@@ -516,12 +796,12 @@ void VaapiVideoDecodeAccelerator::FinishFlush() {
void VaapiVideoDecodeAccelerator::ResetTask() {
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
- base::AutoLock auto_lock(lock_);
-
// All the decoding tasks from before the reset request from client are done
// by now, as this task was scheduled after them and client is expected not
// to call Decode() after Reset() and before NotifyResetDone.
- decoder_.Reset();
+ decoder_->Reset();
+
+ base::AutoLock auto_lock(lock_);
// Return current input buffer, if present.
if (curr_input_buffer_.get())
@@ -552,7 +832,7 @@ void VaapiVideoDecodeAccelerator::Reset() {
&VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
input_ready_.Signal();
- output_ready_.Signal();
+ surfaces_available_.Signal();
}
void VaapiVideoDecodeAccelerator::FinishReset() {
@@ -567,6 +847,9 @@ void VaapiVideoDecodeAccelerator::FinishReset() {
state_ = kIdle;
num_stream_bufs_at_decoder_ = 0;
+ while(!pending_output_cbs_.empty())
+ pending_output_cbs_.pop();
+
message_loop_->PostTask(FROM_HERE, base::Bind(
&Client::NotifyResetDone, client_));
@@ -602,12 +885,11 @@ void VaapiVideoDecodeAccelerator::Cleanup() {
decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
&base::WaitableEvent::Signal, base::Unretained(&waiter)));
input_ready_.Signal();
- output_ready_.Signal();
+ surfaces_available_.Signal();
waiter.Wait();
decoder_thread_.Stop();
}
- decoder_.Destroy();
state_ = kUninitialized;
}
@@ -617,14 +899,4 @@ void VaapiVideoDecodeAccelerator::Destroy() {
delete this;
}
-// static
-void VaapiVideoDecodeAccelerator::PreSandboxInitialization() {
- VaapiH264Decoder::PreSandboxInitialization();
-}
-
-// static
-bool VaapiVideoDecodeAccelerator::PostSandboxInitialization() {
- return VaapiH264Decoder::PostSandboxInitialization();
-}
-
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698