1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include <linux/videodev2.h>
10 #include <sys/eventfd.h>
11 #include <sys/ioctl.h>
14 #include "base/bind.h"
15 #include "base/debug/trace_event.h"
16 #include "base/memory/shared_memory.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/message_loop/message_loop_proxy.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "content/common/gpu/media/exynos_video_decode_accelerator.h"
21 #include "content/common/gpu/media/h264_parser.h"
22 #include "ui/gl/scoped_binders.h"
26 #define NOTIFY_ERROR(x) \
28 SetDecoderState(kError); \
29 DLOG(ERROR) << "calling NotifyError(): " << x; \
33 #define IOCTL_OR_ERROR_RETURN(fd, type, arg) \
35 if (HANDLE_EINTR(ioctl(fd, type, arg) != 0)) { \
36 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
37 NOTIFY_ERROR(PLATFORM_FAILURE); \
42 #define IOCTL_OR_ERROR_RETURN_FALSE(fd, type, arg) \
44 if (HANDLE_EINTR(ioctl(fd, type, arg) != 0)) { \
45 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
46 NOTIFY_ERROR(PLATFORM_FAILURE); \
53 // TODO(posciak): remove once we update linux-headers.
54 #ifndef V4L2_EVENT_RESOLUTION_CHANGE
55 #define V4L2_EVENT_RESOLUTION_CHANGE 5
58 const char kExynosMfcDevice[] = "/dev/mfc-dec";
59 const char kExynosGscDevice[] = "/dev/gsc1";
60 const char kMaliDriver[] = "libmali.so";
62 typedef EGLBoolean (*MaliEglImageGetBufferExtPhandleFunc)(EGLImageKHR, EGLint*,
65 void* libmali_handle = NULL;
66 MaliEglImageGetBufferExtPhandleFunc
67 mali_egl_image_get_buffer_ext_phandle = NULL;
68 } // anonymous namespace
70 struct ExynosVideoDecodeAccelerator::BitstreamBufferRef {
72 base::WeakPtr<Client>& client,
73 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy,
74 base::SharedMemory* shm,
77 ~BitstreamBufferRef();
78 const base::WeakPtr<Client> client;
79 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy;
80 const scoped_ptr<base::SharedMemory> shm;
86 struct ExynosVideoDecodeAccelerator::PictureBufferArrayRef {
87 PictureBufferArrayRef(EGLDisplay egl_display, size_t count);
88 ~PictureBufferArrayRef();
90 struct PictureBufferRef {
91 EGLImageKHR egl_image;
96 EGLDisplay const egl_display;
97 std::vector<PictureBufferRef> picture_buffers;
100 struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef {
101 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync);
103 EGLDisplay const egl_display;
107 struct ExynosVideoDecodeAccelerator::PictureRecord {
108 PictureRecord(bool cleared, const media::Picture& picture);
110 bool cleared; // Whether the texture is cleared and safe to render from.
111 media::Picture picture; // The decoded picture.
114 ExynosVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
115 base::WeakPtr<Client>& client,
116 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy,
117 base::SharedMemory* shm, size_t size, int32 input_id)
119 client_message_loop_proxy(client_message_loop_proxy),
126 ExynosVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() {
128 client_message_loop_proxy->PostTask(FROM_HERE, base::Bind(
129 &Client::NotifyEndOfBitstreamBuffer, client, input_id));
133 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::PictureBufferArrayRef(
134 EGLDisplay egl_display, size_t count)
135 : egl_display(egl_display),
136 picture_buffers(count) {
137 for (size_t i = 0; i < picture_buffers.size(); ++i) {
138 PictureBufferRef& buffer = picture_buffers[i];
139 buffer.egl_image = EGL_NO_IMAGE_KHR;
140 buffer.egl_image_fd = -1;
141 buffer.client_id = -1;
145 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::~PictureBufferArrayRef() {
146 for (size_t i = 0; i < picture_buffers.size(); ++i) {
147 PictureBufferRef& buffer = picture_buffers[i];
148 if (buffer.egl_image != EGL_NO_IMAGE_KHR)
149 eglDestroyImageKHR(egl_display, buffer.egl_image);
150 if (buffer.egl_image_fd != -1)
151 HANDLE_EINTR(close(buffer.egl_image_fd));
155 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef(
156 EGLDisplay egl_display, EGLSyncKHR egl_sync)
157 : egl_display(egl_display),
161 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() {
162 if (egl_sync != EGL_NO_SYNC_KHR)
163 eglDestroySyncKHR(egl_display, egl_sync);
166 ExynosVideoDecodeAccelerator::MfcInputRecord::MfcInputRecord()
174 ExynosVideoDecodeAccelerator::MfcInputRecord::~MfcInputRecord() {
177 ExynosVideoDecodeAccelerator::MfcOutputRecord::MfcOutputRecord()
188 ExynosVideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() {
191 ExynosVideoDecodeAccelerator::GscInputRecord::GscInputRecord()
196 ExynosVideoDecodeAccelerator::GscInputRecord::~GscInputRecord() {
199 ExynosVideoDecodeAccelerator::GscOutputRecord::GscOutputRecord()
203 egl_image(EGL_NO_IMAGE_KHR),
204 egl_sync(EGL_NO_SYNC_KHR),
208 ExynosVideoDecodeAccelerator::GscOutputRecord::~GscOutputRecord() {
211 ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord(
213 const media::Picture& picture)
214 : cleared(cleared), picture(picture) {}
216 ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
218 ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator(
219 EGLDisplay egl_display,
220 EGLContext egl_context,
222 const base::WeakPtr<Client>& io_client,
223 const base::Callback<bool(void)>& make_context_current,
224 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
225 : child_message_loop_proxy_(base::MessageLoopProxy::current()),
226 io_message_loop_proxy_(io_message_loop_proxy),
227 weak_this_(base::AsWeakPtr(this)),
228 client_ptr_factory_(client),
229 client_(client_ptr_factory_.GetWeakPtr()),
230 io_client_(io_client),
231 decoder_thread_("ExynosDecoderThread"),
232 decoder_state_(kUninitialized),
233 decoder_delay_bitstream_buffer_id_(-1),
234 decoder_current_input_buffer_(-1),
235 decoder_decode_buffer_tasks_scheduled_(0),
236 decoder_frames_at_client_(0),
237 decoder_flushing_(false),
238 resolution_change_pending_(false),
239 resolution_change_reset_pending_(false),
240 decoder_partial_frame_pending_(false),
242 mfc_input_streamon_(false),
243 mfc_input_buffer_queued_count_(0),
244 mfc_output_streamon_(false),
245 mfc_output_buffer_queued_count_(0),
246 mfc_output_buffer_pixelformat_(0),
247 mfc_output_dpb_size_(0),
249 gsc_input_streamon_(false),
250 gsc_input_buffer_queued_count_(0),
251 gsc_output_streamon_(false),
252 gsc_output_buffer_queued_count_(0),
253 picture_clearing_count_(0),
254 device_poll_thread_("ExynosDevicePollThread"),
255 device_poll_interrupt_fd_(-1),
256 make_context_current_(make_context_current),
257 egl_display_(egl_display),
258 egl_context_(egl_context),
259 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {}
261 ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() {
262 DCHECK(!decoder_thread_.IsRunning());
263 DCHECK(!device_poll_thread_.IsRunning());
265 if (device_poll_interrupt_fd_ != -1) {
266 HANDLE_EINTR(close(device_poll_interrupt_fd_));
267 device_poll_interrupt_fd_ = -1;
270 DestroyGscInputBuffers();
271 DestroyGscOutputBuffers();
272 HANDLE_EINTR(close(gsc_fd_));
276 DestroyMfcInputBuffers();
277 DestroyMfcOutputBuffers();
278 HANDLE_EINTR(close(mfc_fd_));
282 // These maps have members that should be manually destroyed, e.g. file
283 // descriptors, mmap() segments, etc.
284 DCHECK(mfc_input_buffer_map_.empty());
285 DCHECK(mfc_output_buffer_map_.empty());
286 DCHECK(gsc_input_buffer_map_.empty());
287 DCHECK(gsc_output_buffer_map_.empty());
290 bool ExynosVideoDecodeAccelerator::Initialize(
291 media::VideoCodecProfile profile) {
292 DVLOG(3) << "Initialize()";
293 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
294 DCHECK_EQ(decoder_state_, kUninitialized);
297 case media::H264PROFILE_BASELINE:
298 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE";
300 case media::H264PROFILE_MAIN:
301 DVLOG(2) << "Initialize(): profile H264PROFILE_MAIN";
303 case media::H264PROFILE_HIGH:
304 DVLOG(2) << "Initialize(): profile H264PROFILE_HIGH";
306 case media::VP8PROFILE_MAIN:
307 DVLOG(2) << "Initialize(): profile VP8PROFILE_MAIN";
310 DLOG(ERROR) << "Initialize(): unsupported profile=" << profile;
313 video_profile_ = profile;
315 static bool sandbox_initialized = PostSandboxInitialization();
316 if (!sandbox_initialized) {
317 DLOG(ERROR) << "Initialize(): PostSandboxInitialization() failed";
318 NOTIFY_ERROR(PLATFORM_FAILURE);
322 if (egl_display_ == EGL_NO_DISPLAY) {
323 DLOG(ERROR) << "Initialize(): could not get EGLDisplay";
324 NOTIFY_ERROR(PLATFORM_FAILURE);
328 if (egl_context_ == EGL_NO_CONTEXT) {
329 DLOG(ERROR) << "Initialize(): could not get EGLContext";
330 NOTIFY_ERROR(PLATFORM_FAILURE);
334 // We need the context to be initialized to query extensions.
335 if (!make_context_current_.Run()) {
336 DLOG(ERROR) << "Initialize(): could not make context current";
337 NOTIFY_ERROR(PLATFORM_FAILURE);
341 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
342 DLOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync";
343 NOTIFY_ERROR(PLATFORM_FAILURE);
347 // Open the video devices.
348 DVLOG(2) << "Initialize(): opening MFC device: " << kExynosMfcDevice;
349 mfc_fd_ = HANDLE_EINTR(open(kExynosMfcDevice,
350 O_RDWR | O_NONBLOCK | O_CLOEXEC));
352 DPLOG(ERROR) << "Initialize(): could not open MFC device: "
354 NOTIFY_ERROR(PLATFORM_FAILURE);
357 DVLOG(2) << "Initialize(): opening GSC device: " << kExynosGscDevice;
358 gsc_fd_ = HANDLE_EINTR(open(kExynosGscDevice,
359 O_RDWR | O_NONBLOCK | O_CLOEXEC));
361 DPLOG(ERROR) << "Initialize(): could not open GSC device: "
363 NOTIFY_ERROR(PLATFORM_FAILURE);
367 // Create the interrupt fd.
368 DCHECK_EQ(device_poll_interrupt_fd_, -1);
369 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
370 if (device_poll_interrupt_fd_ == -1) {
371 DPLOG(ERROR) << "Initialize(): eventfd() failed";
372 NOTIFY_ERROR(PLATFORM_FAILURE);
376 // Capabilities check.
377 struct v4l2_capability caps;
378 const __u32 kCapsRequired =
379 V4L2_CAP_VIDEO_CAPTURE_MPLANE |
380 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
382 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYCAP, &caps);
383 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
384 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
385 ", caps check failed: 0x" << std::hex << caps.capabilities;
386 NOTIFY_ERROR(PLATFORM_FAILURE);
389 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QUERYCAP, &caps);
390 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
391 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
392 ", caps check failed: 0x" << std::hex << caps.capabilities;
393 NOTIFY_ERROR(PLATFORM_FAILURE);
397 if (!CreateMfcInputBuffers())
400 // MFC output format has to be setup before streaming starts.
401 struct v4l2_format format;
402 memset(&format, 0, sizeof(format));
403 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
404 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
405 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format);
407 // Subscribe to the resolution change event.
408 struct v4l2_event_subscription sub;
409 memset(&sub, 0, sizeof(sub));
410 sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
411 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub);
413 // Initialize format-specific bits.
414 if (video_profile_ >= media::H264PROFILE_MIN &&
415 video_profile_ <= media::H264PROFILE_MAX) {
416 decoder_h264_parser_.reset(new content::H264Parser());
419 if (!decoder_thread_.Start()) {
420 DLOG(ERROR) << "Initialize(): decoder thread failed to start";
421 NOTIFY_ERROR(PLATFORM_FAILURE);
425 SetDecoderState(kInitialized);
427 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
428 &Client::NotifyInitializeDone, client_));
432 void ExynosVideoDecodeAccelerator::Decode(
433 const media::BitstreamBuffer& bitstream_buffer) {
434 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id()
435 << ", size=" << bitstream_buffer.size();
436 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
438 // DecodeTask() will take care of running a DecodeBufferTask().
439 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
440 &ExynosVideoDecodeAccelerator::DecodeTask, base::Unretained(this),
444 void ExynosVideoDecodeAccelerator::AssignPictureBuffers(
445 const std::vector<media::PictureBuffer>& buffers) {
446 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size();
447 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
449 if (buffers.size() != gsc_output_buffer_map_.size()) {
450 DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture"
451 " buffers. (Got " << buffers.size() << ", requested " <<
452 gsc_output_buffer_map_.size() << ")";
453 NOTIFY_ERROR(INVALID_ARGUMENT);
457 if (!make_context_current_.Run()) {
458 DLOG(ERROR) << "AssignPictureBuffers(): could not make context current";
459 NOTIFY_ERROR(PLATFORM_FAILURE);
463 scoped_ptr<PictureBufferArrayRef> pic_buffers_ref(
464 new PictureBufferArrayRef(egl_display_, buffers.size()));
466 const static EGLint kImageAttrs[] = {
467 EGL_IMAGE_PRESERVED_KHR, 0,
470 Display* x_display = base::MessagePumpForUI::GetDefaultXDisplay();
471 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_2D, 0);
472 for (size_t i = 0; i < pic_buffers_ref->picture_buffers.size(); ++i) {
473 DCHECK(buffers[i].size() == frame_buffer_size_);
474 PictureBufferArrayRef::PictureBufferRef& buffer =
475 pic_buffers_ref->picture_buffers[i];
476 // Create the X pixmap and then create an EGLImageKHR from it, so we can
477 // get dma_buf backing.
478 Pixmap pixmap = XCreatePixmap(x_display,
479 RootWindow(x_display, 0),
480 frame_buffer_size_.width(),
481 frame_buffer_size_.height(),
484 DLOG(ERROR) << "AssignPictureBuffers(): could not create X pixmap";
485 NOTIFY_ERROR(PLATFORM_FAILURE);
488 glBindTexture(GL_TEXTURE_2D, buffers[i].texture_id());
489 EGLImageKHR egl_image = eglCreateImageKHR(
490 egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
491 (EGLClientBuffer)pixmap, kImageAttrs);
492 // We can free the X pixmap immediately -- according to the
493 // EGL_KHR_image_base spec, the backing storage does not go away until the
494 // last referencing EGLImage is destroyed.
495 XFreePixmap(x_display, pixmap);
496 if (egl_image == EGL_NO_IMAGE_KHR) {
497 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
498 NOTIFY_ERROR(PLATFORM_FAILURE);
501 buffer.egl_image = egl_image;
503 if (!mali_egl_image_get_buffer_ext_phandle(buffer.egl_image, NULL, &fd)) {
504 DLOG(ERROR) << "AssignPictureBuffers(): "
505 << "could not get EGLImageKHR dmabuf fd";
506 NOTIFY_ERROR(PLATFORM_FAILURE);
509 buffer.egl_image_fd = fd;
510 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image);
511 buffer.client_id = buffers[i].id();
513 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
514 &ExynosVideoDecodeAccelerator::AssignPictureBuffersTask,
515 base::Unretained(this), base::Passed(&pic_buffers_ref)));
518 void ExynosVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
519 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id;
520 // Must be run on child thread, as we'll insert a sync in the EGL context.
521 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
523 if (!make_context_current_.Run()) {
524 DLOG(ERROR) << "ReusePictureBuffer(): could not make context current";
525 NOTIFY_ERROR(PLATFORM_FAILURE);
529 EGLSyncKHR egl_sync =
530 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
531 if (egl_sync == EGL_NO_SYNC_KHR) {
532 DLOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed";
533 NOTIFY_ERROR(PLATFORM_FAILURE);
537 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef(
538 egl_display_, egl_sync));
539 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
540 &ExynosVideoDecodeAccelerator::ReusePictureBufferTask,
541 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref)));
544 void ExynosVideoDecodeAccelerator::Flush() {
545 DVLOG(3) << "Flush()";
546 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
547 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
548 &ExynosVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
551 void ExynosVideoDecodeAccelerator::Reset() {
552 DVLOG(3) << "Reset()";
553 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
554 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
555 &ExynosVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
558 void ExynosVideoDecodeAccelerator::Destroy() {
559 DVLOG(3) << "Destroy()";
560 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
562 // We're destroying; cancel all callbacks.
563 client_ptr_factory_.InvalidateWeakPtrs();
565 // If the decoder thread is running, destroy using posted task.
566 if (decoder_thread_.IsRunning()) {
567 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
568 &ExynosVideoDecodeAccelerator::DestroyTask, base::Unretained(this)));
569 // DestroyTask() will cause the decoder_thread_ to flush all tasks.
570 decoder_thread_.Stop();
572 // Otherwise, call the destroy task directly.
576 // Set to kError state just in case.
577 SetDecoderState(kError);
582 bool ExynosVideoDecodeAccelerator::CanDecodeOnIOThread() { return true; }
585 void ExynosVideoDecodeAccelerator::PreSandboxInitialization() {
586 DVLOG(3) << "PreSandboxInitialization()";
589 libmali_handle = dlopen(kMaliDriver, RTLD_LAZY | RTLD_LOCAL);
590 if (libmali_handle == NULL) {
591 DPLOG(ERROR) << "failed to dlopen() " << kMaliDriver << ": " << dlerror();
596 bool ExynosVideoDecodeAccelerator::PostSandboxInitialization() {
597 DVLOG(3) << "PostSandboxInitialization()";
598 if (libmali_handle == NULL) {
599 DLOG(ERROR) << "PostSandboxInitialization(): no " << kMaliDriver
605 mali_egl_image_get_buffer_ext_phandle =
606 reinterpret_cast<MaliEglImageGetBufferExtPhandleFunc>(
607 dlsym(libmali_handle, "mali_egl_image_get_buffer_ext_phandle"));
608 if (mali_egl_image_get_buffer_ext_phandle == NULL) {
609 DPLOG(ERROR) << "PostSandboxInitialization(): failed to dlsym() "
610 << "mali_egl_image_get_buffer_ext_phandle: " << dlerror();
617 void ExynosVideoDecodeAccelerator::DecodeTask(
618 const media::BitstreamBuffer& bitstream_buffer) {
619 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id();
620 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
621 DCHECK_NE(decoder_state_, kUninitialized);
622 TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id",
623 bitstream_buffer.id());
625 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
626 io_client_, io_message_loop_proxy_,
627 new base::SharedMemory(bitstream_buffer.handle(), true),
628 bitstream_buffer.size(), bitstream_buffer.id()));
629 if (!bitstream_record->shm->Map(bitstream_buffer.size())) {
630 DLOG(ERROR) << "Decode(): could not map bitstream_buffer";
631 NOTIFY_ERROR(UNREADABLE_INPUT);
634 DVLOG(3) << "Decode(): mapped to addr=" << bitstream_record->shm->memory();
636 if (decoder_state_ == kResetting || decoder_flushing_) {
637 // In the case that we're resetting or flushing, we need to delay decoding
638 // the BitstreamBuffers that come after the Reset() or Flush() call. When
639 // we're here, we know that this DecodeTask() was scheduled by a Decode()
640 // call that came after (in the client thread) the Reset() or Flush() call;
641 // thus set up the delay if necessary.
642 if (decoder_delay_bitstream_buffer_id_ == -1)
643 decoder_delay_bitstream_buffer_id_ = bitstream_record->input_id;
644 } else if (decoder_state_ == kError) {
645 DVLOG(2) << "DecodeTask(): early out: kError state";
649 decoder_input_queue_.push_back(
650 linked_ptr<BitstreamBufferRef>(bitstream_record.release()));
651 decoder_decode_buffer_tasks_scheduled_++;
655 void ExynosVideoDecodeAccelerator::DecodeBufferTask() {
656 DVLOG(3) << "DecodeBufferTask()";
657 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
658 DCHECK_NE(decoder_state_, kUninitialized);
659 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask");
661 decoder_decode_buffer_tasks_scheduled_--;
663 if (decoder_state_ == kResetting) {
664 DVLOG(2) << "DecodeBufferTask(): early out: kResetting state";
666 } else if (decoder_state_ == kError) {
667 DVLOG(2) << "DecodeBufferTask(): early out: kError state";
669 } else if (decoder_state_ == kChangingResolution) {
670 DVLOG(2) << "DecodeBufferTask(): early out: resolution change pending";
674 if (decoder_current_bitstream_buffer_ == NULL) {
675 if (decoder_input_queue_.empty()) {
676 // We're waiting for a new buffer -- exit without scheduling a new task.
679 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front();
680 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) {
681 // We're asked to delay decoding on this and subsequent buffers.
685 // Setup to use the next buffer.
686 decoder_current_bitstream_buffer_.reset(buffer_ref.release());
687 decoder_input_queue_.pop_front();
688 DVLOG(3) << "DecodeBufferTask(): reading input_id="
689 << decoder_current_bitstream_buffer_->input_id
690 << ", addr=" << (decoder_current_bitstream_buffer_->shm ?
691 decoder_current_bitstream_buffer_->shm->memory() :
693 << ", size=" << decoder_current_bitstream_buffer_->size;
695 bool schedule_task = false;
696 const size_t size = decoder_current_bitstream_buffer_->size;
697 size_t decoded_size = 0;
699 const int32 input_id = decoder_current_bitstream_buffer_->input_id;
701 // This is a buffer queued from the client that has zero size. Skip.
702 schedule_task = true;
704 // This is a buffer of zero size, queued to flush the pipe. Flush.
705 DCHECK_EQ(decoder_current_bitstream_buffer_->shm.get(),
706 static_cast<base::SharedMemory*>(NULL));
707 // Enqueue a buffer guaranteed to be empty. To do that, we flush the
708 // current input, enqueue no data to the next frame, then flush that down.
709 schedule_task = true;
710 if (decoder_current_input_buffer_ != -1 &&
711 mfc_input_buffer_map_[decoder_current_input_buffer_].input_id !=
713 schedule_task = FlushInputFrame();
715 if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) {
716 DVLOG(2) << "DecodeBufferTask(): enqueued flush buffer";
717 decoder_partial_frame_pending_ = false;
718 schedule_task = true;
720 // If we failed to enqueue the empty buffer (due to pipeline
721 // backpressure), don't advance the bitstream buffer queue, and don't
722 // schedule the next task. This bitstream buffer queue entry will get
723 // reprocessed when the pipeline frees up.
724 schedule_task = false;
728 // This is a buffer queued from the client, with actual contents. Decode.
729 const uint8* const data =
730 reinterpret_cast<const uint8*>(
731 decoder_current_bitstream_buffer_->shm->memory()) +
732 decoder_current_bitstream_buffer_->bytes_used;
733 const size_t data_size =
734 decoder_current_bitstream_buffer_->size -
735 decoder_current_bitstream_buffer_->bytes_used;
736 if (!AdvanceFrameFragment(data, data_size, &decoded_size)) {
737 NOTIFY_ERROR(UNREADABLE_INPUT);
740 // AdvanceFrameFragment should not return a size larger than the buffer
741 // size, even on invalid data.
742 CHECK_LE(decoded_size, data_size);
744 switch (decoder_state_) {
747 schedule_task = DecodeBufferInitial(data, decoded_size, &decoded_size);
750 schedule_task = DecodeBufferContinue(data, decoded_size);
753 NOTIFY_ERROR(ILLEGAL_STATE);
757 if (decoder_state_ == kError) {
758 // Failed during decode.
763 decoder_current_bitstream_buffer_->bytes_used += decoded_size;
764 if (decoder_current_bitstream_buffer_->bytes_used ==
765 decoder_current_bitstream_buffer_->size) {
766 // Our current bitstream buffer is done; return it.
767 int32 input_id = decoder_current_bitstream_buffer_->input_id;
768 DVLOG(3) << "DecodeBufferTask(): finished input_id=" << input_id;
769 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer().
770 decoder_current_bitstream_buffer_.reset();
772 ScheduleDecodeBufferTaskIfNeeded();
776 bool ExynosVideoDecodeAccelerator::AdvanceFrameFragment(
780 if (video_profile_ >= media::H264PROFILE_MIN &&
781 video_profile_ <= media::H264PROFILE_MAX) {
782 // For H264, we need to feed HW one frame at a time. This is going to take
783 // some parsing of our input stream.
784 decoder_h264_parser_->SetStream(data, size);
785 content::H264NALU nalu;
786 content::H264Parser::Result result;
789 // Keep on peeking the next NALs while they don't indicate a frame
792 bool end_of_frame = false;
793 result = decoder_h264_parser_->AdvanceToNextNALU(&nalu);
794 if (result == content::H264Parser::kInvalidStream ||
795 result == content::H264Parser::kUnsupportedStream)
797 if (result == content::H264Parser::kEOStream) {
798 // We've reached the end of the buffer before finding a frame boundary.
799 decoder_partial_frame_pending_ = true;
802 switch (nalu.nal_unit_type) {
803 case content::H264NALU::kNonIDRSlice:
804 case content::H264NALU::kIDRSlice:
807 // For these two, if the "first_mb_in_slice" field is zero, start a
808 // new frame and return. This field is Exp-Golomb coded starting on
809 // the eighth data bit of the NAL; a zero value is encoded with a
810 // leading '1' bit in the byte, which we can detect as the byte being
811 // (unsigned) greater than or equal to 0x80.
812 if (nalu.data[1] >= 0x80) {
817 case content::H264NALU::kSPS:
818 case content::H264NALU::kPPS:
819 case content::H264NALU::kEOSeq:
820 case content::H264NALU::kEOStream:
821 // These unconditionally signal a frame boundary.
825 // For all others, keep going.
829 if (!decoder_partial_frame_pending_ && *endpos == 0) {
830 // The frame was previously restarted, and we haven't filled the
831 // current frame with any contents yet. Start the new frame here and
832 // continue parsing NALs.
834 // The frame wasn't previously restarted and/or we have contents for
835 // the current frame; signal the start of a new frame here: we don't
836 // have a partial frame anymore.
837 decoder_partial_frame_pending_ = false;
841 *endpos = (nalu.data + nalu.size) - data;
846 DCHECK_GE(video_profile_, media::VP8PROFILE_MIN);
847 DCHECK_LE(video_profile_, media::VP8PROFILE_MAX);
848 // For VP8, we can just dump the entire buffer. No fragmentation needed,
849 // and we never return a partial frame.
851 decoder_partial_frame_pending_ = false;
856 void ExynosVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() {
857 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
859 // If we're behind on tasks, schedule another one.
860 int buffers_to_decode = decoder_input_queue_.size();
861 if (decoder_current_bitstream_buffer_ != NULL)
863 if (decoder_decode_buffer_tasks_scheduled_ < buffers_to_decode) {
864 decoder_decode_buffer_tasks_scheduled_++;
865 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
866 &ExynosVideoDecodeAccelerator::DecodeBufferTask,
867 base::Unretained(this)));
871 bool ExynosVideoDecodeAccelerator::DecodeBufferInitial(
872 const void* data, size_t size, size_t* endpos) {
873 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size;
874 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
875 DCHECK_NE(decoder_state_, kUninitialized);
876 DCHECK_NE(decoder_state_, kDecoding);
877 DCHECK(!device_poll_thread_.IsRunning());
878 // Initial decode. We haven't been able to get output stream format info yet.
879 // Get it, and start decoding.
881 // Copy in and send to HW.
882 if (!AppendToInputFrame(data, size))
885 // If we only have a partial frame, don't flush and process yet.
886 if (decoder_partial_frame_pending_)
889 if (!FlushInputFrame())
895 // Check and see if we have format info yet.
896 struct v4l2_format format;
898 if (!GetFormatInfo(&format, &again))
902 // Need more stream to decode format, return true and schedule next buffer.
907 // Run this initialization only on first startup.
908 if (decoder_state_ == kInitialized) {
909 DVLOG(3) << "DecodeBufferInitial(): running initialization";
910 // Success! Setup our parameters.
911 if (!CreateBuffersForFormat(format))
914 // MFC expects to process the initial buffer once during stream init to
915 // configure stream parameters, but will not consume the steam data on that
916 // iteration. Subsequent iterations (including after reset) do not require
917 // the stream init step.
923 // StartDevicePoll will raise the error if there is one.
924 if (!StartDevicePoll())
927 decoder_state_ = kDecoding;
928 ScheduleDecodeBufferTaskIfNeeded();
932 bool ExynosVideoDecodeAccelerator::DecodeBufferContinue(
933 const void* data, size_t size) {
934 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size;
935 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
936 DCHECK_EQ(decoder_state_, kDecoding);
938 // Both of these calls will set kError state if they fail.
939 // Only flush the frame if it's complete.
940 return (AppendToInputFrame(data, size) &&
941 (decoder_partial_frame_pending_ || FlushInputFrame()));
944 bool ExynosVideoDecodeAccelerator::AppendToInputFrame(
945 const void* data, size_t size) {
946 DVLOG(3) << "AppendToInputFrame()";
947 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
948 DCHECK_NE(decoder_state_, kUninitialized);
949 DCHECK_NE(decoder_state_, kResetting);
950 DCHECK_NE(decoder_state_, kError);
951 // This routine can handle data == NULL and size == 0, which occurs when
952 // we queue an empty buffer for the purposes of flushing the pipe.
954 // Flush if we're too big
955 if (decoder_current_input_buffer_ != -1) {
956 MfcInputRecord& input_record =
957 mfc_input_buffer_map_[decoder_current_input_buffer_];
958 if (input_record.bytes_used + size > input_record.length) {
959 if (!FlushInputFrame())
961 decoder_current_input_buffer_ = -1;
965 // Try to get an available input buffer
966 if (decoder_current_input_buffer_ == -1) {
967 if (mfc_free_input_buffers_.empty()) {
968 // See if we can get more free buffers from HW
970 if (mfc_free_input_buffers_.empty()) {
972 DVLOG(2) << "AppendToInputFrame(): stalled for input buffers";
976 decoder_current_input_buffer_ = mfc_free_input_buffers_.back();
977 mfc_free_input_buffers_.pop_back();
978 MfcInputRecord& input_record =
979 mfc_input_buffer_map_[decoder_current_input_buffer_];
980 DCHECK_EQ(input_record.bytes_used, 0);
981 DCHECK_EQ(input_record.input_id, -1);
982 DCHECK(decoder_current_bitstream_buffer_ != NULL);
983 input_record.input_id = decoder_current_bitstream_buffer_->input_id;
986 DCHECK(data != NULL || size == 0);
988 // If we asked for an empty buffer, return now. We return only after
989 // getting the next input buffer, since we might actually want an empty
990 // input buffer for flushing purposes.
994 // Copy in to the buffer.
995 MfcInputRecord& input_record =
996 mfc_input_buffer_map_[decoder_current_input_buffer_];
997 if (size > input_record.length - input_record.bytes_used) {
998 LOG(ERROR) << "AppendToInputFrame(): over-size frame, erroring";
999 NOTIFY_ERROR(UNREADABLE_INPUT);
1003 reinterpret_cast<uint8*>(input_record.address) + input_record.bytes_used,
1006 input_record.bytes_used += size;
1011 bool ExynosVideoDecodeAccelerator::FlushInputFrame() {
1012 DVLOG(3) << "FlushInputFrame()";
1013 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1014 DCHECK_NE(decoder_state_, kUninitialized);
1015 DCHECK_NE(decoder_state_, kResetting);
1016 DCHECK_NE(decoder_state_, kError);
1018 if (decoder_current_input_buffer_ == -1)
1021 MfcInputRecord& input_record =
1022 mfc_input_buffer_map_[decoder_current_input_buffer_];
1023 DCHECK_NE(input_record.input_id, -1);
1024 DCHECK(input_record.input_id != kFlushBufferId ||
1025 input_record.bytes_used == 0);
1026 // * if input_id >= 0, this input buffer was prompted by a bitstream buffer we
1027 // got from the client. We can skip it if it is empty.
1028 // * if input_id < 0 (should be kFlushBufferId in this case), this input
1029 // buffer was prompted by a flush buffer, and should be queued even when
1031 if (input_record.input_id >= 0 && input_record.bytes_used == 0) {
1032 input_record.input_id = -1;
1033 mfc_free_input_buffers_.push_back(decoder_current_input_buffer_);
1034 decoder_current_input_buffer_ = -1;
1039 mfc_input_ready_queue_.push_back(decoder_current_input_buffer_);
1040 decoder_current_input_buffer_ = -1;
1041 DVLOG(3) << "FlushInputFrame(): submitting input_id="
1042 << input_record.input_id;
1043 // Kick the MFC once since there's new available input for it.
1046 return (decoder_state_ != kError);
1049 void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask(
1050 scoped_ptr<PictureBufferArrayRef> pic_buffers) {
1051 DVLOG(3) << "AssignPictureBuffersTask()";
1052 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1053 DCHECK_NE(decoder_state_, kUninitialized);
1054 TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask");
1056 // We run AssignPictureBuffersTask even if we're in kResetting.
1057 if (decoder_state_ == kError) {
1058 DVLOG(2) << "AssignPictureBuffersTask(): early out: kError state";
1062 DCHECK_EQ(pic_buffers->picture_buffers.size(), gsc_output_buffer_map_.size());
1063 for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) {
1064 // We should be blank right now.
1065 GscOutputRecord& output_record = gsc_output_buffer_map_[i];
1066 DCHECK_EQ(output_record.fd, -1);
1067 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
1068 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1069 DCHECK_EQ(output_record.picture_id, -1);
1070 DCHECK_EQ(output_record.cleared, false);
1071 PictureBufferArrayRef::PictureBufferRef& buffer =
1072 pic_buffers->picture_buffers[i];
1073 output_record.fd = buffer.egl_image_fd;
1074 output_record.egl_image = buffer.egl_image;
1075 output_record.picture_id = buffer.client_id;
1077 // Take ownership of the EGLImage and fd.
1078 buffer.egl_image = EGL_NO_IMAGE_KHR;
1079 buffer.egl_image_fd = -1;
1080 // And add this buffer to the free list.
1081 gsc_free_output_buffers_.push_back(i);
1084 // We got buffers! Kick the GSC.
1087 if (decoder_state_ == kChangingResolution)
1088 ResumeAfterResolutionChange();
1091 void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
1092 DVLOG(3) << "ServiceDeviceTask()";
1093 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1094 DCHECK_NE(decoder_state_, kUninitialized);
1095 DCHECK_NE(decoder_state_, kInitialized);
1096 DCHECK_NE(decoder_state_, kAfterReset);
1097 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask");
1099 if (decoder_state_ == kResetting) {
1100 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state";
1102 } else if (decoder_state_ == kError) {
1103 DVLOG(2) << "ServiceDeviceTask(): early out: kError state";
1105 } else if (decoder_state_ == kChangingResolution) {
1106 DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state";
1110 if (mfc_event_pending)
1117 // Clear the interrupt fd.
1118 if (!ClearDevicePollInterrupt())
1121 unsigned int poll_fds = 0;
1122 // Add MFC fd, if we should poll on it.
1123 // MFC can be polled as soon as either input or output buffers are queued.
1124 if (mfc_input_buffer_queued_count_ + mfc_output_buffer_queued_count_ > 0)
1125 poll_fds |= kPollMfc;
1126 // Add GSC fd, if we should poll on it.
1127 // GSC has to wait until both input and output buffers are queued.
1128 if (gsc_input_buffer_queued_count_ > 0 && gsc_output_buffer_queued_count_ > 0)
1129 poll_fds |= kPollGsc;
1131 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(),
1133 // * device_poll_thread_ is running normally
1134 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask()
1135 // shut it down, in which case we're either in kResetting or kError states
1136 // respectively, and we should have early-outed already.
1137 DCHECK(device_poll_thread_.message_loop());
1138 // Queue the DevicePollTask() now.
1139 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1140 &ExynosVideoDecodeAccelerator::DevicePollTask,
1141 base::Unretained(this),
1144 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC["
1145 << decoder_input_queue_.size() << "->"
1146 << mfc_input_ready_queue_.size() << "] => MFC["
1147 << mfc_free_input_buffers_.size() << "+"
1148 << mfc_input_buffer_queued_count_ << "/"
1149 << mfc_input_buffer_map_.size() << "->"
1150 << mfc_free_output_buffers_.size() << "+"
1151 << mfc_output_buffer_queued_count_ << "/"
1152 << mfc_output_buffer_map_.size() << "] => "
1153 << mfc_output_gsc_input_queue_.size() << " => GSC["
1154 << gsc_free_input_buffers_.size() << "+"
1155 << gsc_input_buffer_queued_count_ << "/"
1156 << gsc_input_buffer_map_.size() << "->"
1157 << gsc_free_output_buffers_.size() << "+"
1158 << gsc_output_buffer_queued_count_ << "/"
1159 << gsc_output_buffer_map_.size() << "] => VDA["
1160 << decoder_frames_at_client_ << "]";
1162 ScheduleDecodeBufferTaskIfNeeded();
1163 StartResolutionChangeIfNeeded();
1166 void ExynosVideoDecodeAccelerator::EnqueueMfc() {
1167 DVLOG(3) << "EnqueueMfc()";
1168 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1169 DCHECK_NE(decoder_state_, kUninitialized);
1170 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueMfc");
1172 // Drain the pipe of completed decode buffers.
1173 const int old_mfc_inputs_queued = mfc_input_buffer_queued_count_;
1174 while (!mfc_input_ready_queue_.empty()) {
1175 if (!EnqueueMfcInputRecord())
1178 if (old_mfc_inputs_queued == 0 && mfc_input_buffer_queued_count_ != 0) {
1179 // We just started up a previously empty queue.
1180 // Queue state changed; signal interrupt.
1181 if (!SetDevicePollInterrupt())
1183 // Start VIDIOC_STREAMON if we haven't yet.
1184 if (!mfc_input_streamon_) {
1185 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1186 IOCTL_OR_ERROR_RETURN(mfc_fd_, VIDIOC_STREAMON, &type);
1187 mfc_input_streamon_ = true;
1191 // Enqueue all the MFC outputs we can.
1192 const int old_mfc_outputs_queued = mfc_output_buffer_queued_count_;
1193 while (!mfc_free_output_buffers_.empty()) {
1194 if (!EnqueueMfcOutputRecord())
1197 if (old_mfc_outputs_queued == 0 && mfc_output_buffer_queued_count_ != 0) {
1198 // We just started up a previously empty queue.
1199 // Queue state changed; signal interrupt.
1200 if (!SetDevicePollInterrupt())
1202 // Start VIDIOC_STREAMON if we haven't yet.
1203 if (!mfc_output_streamon_) {
1204 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1205 IOCTL_OR_ERROR_RETURN(mfc_fd_, VIDIOC_STREAMON, &type);
1206 mfc_output_streamon_ = true;
1211 void ExynosVideoDecodeAccelerator::DequeueMfcEvents() {
1212 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1213 DCHECK_EQ(decoder_state_, kDecoding);
1214 DVLOG(3) << "DequeueMfcEvents()";
1216 struct v4l2_event ev;
1217 memset(&ev, 0, sizeof(ev));
1219 while (ioctl(mfc_fd_, VIDIOC_DQEVENT, &ev) == 0) {
1220 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
1221 DVLOG(3) << "DequeueMfcEvents(): got resolution change event.";
1222 DCHECK(!resolution_change_pending_);
1223 resolution_change_pending_ = true;
1225 DLOG(FATAL) << "DequeueMfcEvents(): got an event (" << ev.type
1226 << ") we haven't subscribed to.";
1231 void ExynosVideoDecodeAccelerator::DequeueMfc() {
1232 DVLOG(3) << "DequeueMfc()";
1233 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1234 DCHECK_NE(decoder_state_, kUninitialized);
1235 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc");
1237 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free
1239 struct v4l2_buffer dqbuf;
1240 struct v4l2_plane planes[2];
1241 while (mfc_input_buffer_queued_count_ > 0) {
1242 DCHECK(mfc_input_streamon_);
1243 memset(&dqbuf, 0, sizeof(dqbuf));
1244 memset(planes, 0, sizeof(planes));
1245 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1246 dqbuf.memory = V4L2_MEMORY_MMAP;
1247 dqbuf.m.planes = planes;
1249 if (ioctl(mfc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) {
1250 if (errno == EAGAIN) {
1251 // EAGAIN if we're just out of buffers to dequeue.
1254 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF";
1255 NOTIFY_ERROR(PLATFORM_FAILURE);
1258 MfcInputRecord& input_record = mfc_input_buffer_map_[dqbuf.index];
1259 DCHECK(input_record.at_device);
1260 mfc_free_input_buffers_.push_back(dqbuf.index);
1261 input_record.at_device = false;
1262 input_record.bytes_used = 0;
1263 input_record.input_id = -1;
1264 mfc_input_buffer_queued_count_--;
1267 // Dequeue completed MFC output (VIDEO_CAPTURE) buffers, and queue to the
1269 while (mfc_output_buffer_queued_count_ > 0) {
1270 DCHECK(mfc_output_streamon_);
1271 memset(&dqbuf, 0, sizeof(dqbuf));
1272 memset(planes, 0, sizeof(planes));
1273 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1274 dqbuf.memory = V4L2_MEMORY_MMAP;
1275 dqbuf.m.planes = planes;
1277 if (ioctl(mfc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) {
1278 if (errno == EAGAIN) {
1279 // EAGAIN if we're just out of buffers to dequeue.
1282 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF";
1283 NOTIFY_ERROR(PLATFORM_FAILURE);
1286 MfcOutputRecord& output_record = mfc_output_buffer_map_[dqbuf.index];
1287 DCHECK(output_record.at_device);
1288 output_record.at_device = false;
1289 output_record.bytes_used[0] = dqbuf.m.planes[0].bytesused;
1290 output_record.bytes_used[1] = dqbuf.m.planes[1].bytesused;
1291 if (output_record.bytes_used[0] + output_record.bytes_used[1] == 0) {
1292 // This is an empty output buffer returned as part of a flush.
1293 mfc_free_output_buffers_.push_back(dqbuf.index);
1294 output_record.input_id = -1;
1296 // This is an output buffer with contents to pass down the pipe.
1297 mfc_output_gsc_input_queue_.push_back(dqbuf.index);
1298 output_record.input_id = dqbuf.timestamp.tv_sec;
1299 DCHECK(output_record.input_id >= 0);
1300 DVLOG(3) << "DequeueMfc(): dequeued input_id=" << output_record.input_id;
1301 // We don't count this output buffer dequeued yet, or add it to the free
1302 // list, as it has data GSC needs to process.
1304 // We have new frames in mfc_output_gsc_input_queue_. Kick the pipe.
1305 SetDevicePollInterrupt();
1307 mfc_output_buffer_queued_count_--;
1310 NotifyFlushDoneIfNeeded();
1313 void ExynosVideoDecodeAccelerator::EnqueueGsc() {
1314 DVLOG(3) << "EnqueueGsc()";
1315 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1316 DCHECK_NE(decoder_state_, kUninitialized);
1317 DCHECK_NE(decoder_state_, kInitialized);
1318 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueGsc");
1320 // Drain the pipe of completed MFC output buffers.
1321 const int old_gsc_inputs_queued = gsc_input_buffer_queued_count_;
1322 while (!mfc_output_gsc_input_queue_.empty() &&
1323 !gsc_free_input_buffers_.empty()) {
1324 if (!EnqueueGscInputRecord())
1327 if (old_gsc_inputs_queued == 0 && gsc_input_buffer_queued_count_ != 0) {
1328 // We just started up a previously empty queue.
1329 // Queue state changed; signal interrupt.
1330 if (!SetDevicePollInterrupt())
1332 // Start VIDIOC_STREAMON if we haven't yet.
1333 if (!gsc_input_streamon_) {
1334 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1335 IOCTL_OR_ERROR_RETURN(gsc_fd_, VIDIOC_STREAMON, &type);
1336 gsc_input_streamon_ = true;
1340 if (gsc_input_buffer_queued_count_ != 0 &&
1341 gsc_output_buffer_queued_count_ == 0 &&
1342 !gsc_free_output_buffers_.empty()) {
1343 const int old_gsc_outputs_queued = gsc_output_buffer_queued_count_;
1344 if (!EnqueueGscOutputRecord())
1346 if (old_gsc_outputs_queued == 0 && gsc_output_buffer_queued_count_ != 0) {
1347 // We just started up a previously empty queue.
1348 // Queue state changed; signal interrupt.
1349 if (!SetDevicePollInterrupt())
1351 // Start VIDIOC_STREAMON if we haven't yet.
1352 if (!gsc_output_streamon_) {
1353 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1354 IOCTL_OR_ERROR_RETURN(gsc_fd_, VIDIOC_STREAMON, &type);
1355 gsc_output_streamon_ = true;
1359 // Bug check: GSC is liable to race conditions if more than one buffer is
1360 // simultaneously queued.
1361 DCHECK_GE(1, gsc_output_buffer_queued_count_);
1364 void ExynosVideoDecodeAccelerator::DequeueGsc() {
1365 DVLOG(3) << "DequeueGsc()";
1366 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1367 DCHECK_NE(decoder_state_, kUninitialized);
1368 DCHECK_NE(decoder_state_, kInitialized);
1369 DCHECK_NE(decoder_state_, kAfterReset);
1370 TRACE_EVENT0("Video Decoder", "EVDA::DequeueGsc");
1372 // Dequeue completed GSC input (VIDEO_OUTPUT) buffers, and recycle to the free
1373 // list. Also recycle the corresponding MFC output buffers at this time.
1374 struct v4l2_buffer dqbuf;
1375 struct v4l2_plane planes[2];
1376 while (gsc_input_buffer_queued_count_ > 0) {
1377 DCHECK(gsc_input_streamon_);
1378 memset(&dqbuf, 0, sizeof(dqbuf));
1379 memset(planes, 0, sizeof(planes));
1380 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1381 dqbuf.memory = V4L2_MEMORY_DMABUF;
1382 dqbuf.m.planes = planes;
1384 if (ioctl(gsc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) {
1385 if (errno == EAGAIN) {
1386 // EAGAIN if we're just out of buffers to dequeue.
1389 DPLOG(ERROR) << "DequeueGsc(): ioctl() failed: VIDIOC_DQBUF";
1390 NOTIFY_ERROR(PLATFORM_FAILURE);
1393 GscInputRecord& input_record = gsc_input_buffer_map_[dqbuf.index];
1394 MfcOutputRecord& output_record =
1395 mfc_output_buffer_map_[input_record.mfc_output];
1396 DCHECK(input_record.at_device);
1397 gsc_free_input_buffers_.push_back(dqbuf.index);
1398 mfc_free_output_buffers_.push_back(input_record.mfc_output);
1399 input_record.at_device = false;
1400 input_record.mfc_output = -1;
1401 output_record.input_id = -1;
1402 gsc_input_buffer_queued_count_--;
1405 // Dequeue completed GSC output (VIDEO_CAPTURE) buffers, and send them off to
1406 // the client. Don't recycle to its free list yet -- we can't do that until
1407 // ReusePictureBuffer() returns it to us.
1408 while (gsc_output_buffer_queued_count_ > 0) {
1409 DCHECK(gsc_output_streamon_);
1410 memset(&dqbuf, 0, sizeof(dqbuf));
1411 memset(planes, 0, sizeof(planes));
1412 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1413 dqbuf.memory = V4L2_MEMORY_DMABUF;
1414 dqbuf.m.planes = planes;
1416 if (ioctl(gsc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) {
1417 if (errno == EAGAIN) {
1418 // EAGAIN if we're just out of buffers to dequeue.
1421 DPLOG(ERROR) << "DequeueGsc(): ioctl() failed: VIDIOC_DQBUF";
1422 NOTIFY_ERROR(PLATFORM_FAILURE);
1425 GscOutputRecord& output_record = gsc_output_buffer_map_[dqbuf.index];
1426 DCHECK(output_record.at_device);
1427 DCHECK(!output_record.at_client);
1428 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1429 output_record.at_device = false;
1430 output_record.at_client = true;
1431 gsc_output_buffer_queued_count_--;
1432 DVLOG(3) << "DequeueGsc(): returning input_id=" << dqbuf.timestamp.tv_sec
1433 << " as picture_id=" << output_record.picture_id;
1434 const media::Picture& picture =
1435 media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec);
1436 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture));
1438 output_record.cleared = true;
1439 decoder_frames_at_client_++;
1442 NotifyFlushDoneIfNeeded();
1445 bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() {
1446 DVLOG(3) << "EnqueueMfcInputRecord()";
1447 DCHECK(!mfc_input_ready_queue_.empty());
1449 // Enqueue a MFC input (VIDEO_OUTPUT) buffer.
1450 const int buffer = mfc_input_ready_queue_.back();
1451 MfcInputRecord& input_record = mfc_input_buffer_map_[buffer];
1452 DCHECK(!input_record.at_device);
1453 struct v4l2_buffer qbuf;
1454 struct v4l2_plane qbuf_plane;
1455 memset(&qbuf, 0, sizeof(qbuf));
1456 memset(&qbuf_plane, 0, sizeof(qbuf_plane));
1457 qbuf.index = buffer;
1458 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1459 qbuf.timestamp.tv_sec = input_record.input_id;
1460 qbuf.memory = V4L2_MEMORY_MMAP;
1461 qbuf.m.planes = &qbuf_plane;
1462 qbuf.m.planes[0].bytesused = input_record.bytes_used;
1464 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf);
1465 mfc_input_ready_queue_.pop_back();
1466 input_record.at_device = true;
1467 mfc_input_buffer_queued_count_++;
1468 DVLOG(3) << "EnqueueMfcInputRecord(): enqueued input_id="
1469 << input_record.input_id;
1473 bool ExynosVideoDecodeAccelerator::EnqueueMfcOutputRecord() {
1474 DVLOG(3) << "EnqueueMfcOutputRecord()";
1475 DCHECK(!mfc_free_output_buffers_.empty());
1477 // Enqueue a MFC output (VIDEO_CAPTURE) buffer.
1478 const int buffer = mfc_free_output_buffers_.back();
1479 MfcOutputRecord& output_record = mfc_output_buffer_map_[buffer];
1480 DCHECK(!output_record.at_device);
1481 DCHECK_EQ(output_record.input_id, -1);
1482 struct v4l2_buffer qbuf;
1483 struct v4l2_plane qbuf_planes[2];
1484 memset(&qbuf, 0, sizeof(qbuf));
1485 memset(qbuf_planes, 0, sizeof(qbuf_planes));
1486 qbuf.index = buffer;
1487 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1488 qbuf.memory = V4L2_MEMORY_MMAP;
1489 qbuf.m.planes = qbuf_planes;
1491 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf);
1492 mfc_free_output_buffers_.pop_back();
1493 output_record.at_device = true;
1494 mfc_output_buffer_queued_count_++;
1498 bool ExynosVideoDecodeAccelerator::EnqueueGscInputRecord() {
1499 DVLOG(3) << "EnqueueGscInputRecord()";
1500 DCHECK(!gsc_free_input_buffers_.empty());
1502 // Enqueue a GSC input (VIDEO_OUTPUT) buffer for a complete MFC output
1503 // (VIDEO_CAPTURE) buffer.
1504 const int mfc_buffer = mfc_output_gsc_input_queue_.front();
1505 const int gsc_buffer = gsc_free_input_buffers_.back();
1506 MfcOutputRecord& output_record = mfc_output_buffer_map_[mfc_buffer];
1507 DCHECK(!output_record.at_device);
1508 GscInputRecord& input_record = gsc_input_buffer_map_[gsc_buffer];
1509 DCHECK(!input_record.at_device);
1510 DCHECK_EQ(input_record.mfc_output, -1);
1511 struct v4l2_buffer qbuf;
1512 struct v4l2_plane qbuf_planes[2];
1513 memset(&qbuf, 0, sizeof(qbuf));
1514 memset(qbuf_planes, 0, sizeof(qbuf_planes));
1515 qbuf.index = gsc_buffer;
1516 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1517 qbuf.timestamp.tv_sec = output_record.input_id;
1518 qbuf.memory = V4L2_MEMORY_USERPTR;
1519 qbuf.m.planes = qbuf_planes;
1520 qbuf.m.planes[0].bytesused = output_record.bytes_used[0];
1521 qbuf.m.planes[0].length = mfc_output_buffer_size_[0];
1522 qbuf.m.planes[0].m.userptr = (unsigned long)output_record.address[0];
1523 qbuf.m.planes[1].bytesused = output_record.bytes_used[1];
1524 qbuf.m.planes[1].length = mfc_output_buffer_size_[1];
1525 qbuf.m.planes[1].m.userptr = (unsigned long)output_record.address[1];
1527 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QBUF, &qbuf);
1528 mfc_output_gsc_input_queue_.pop_front();
1529 gsc_free_input_buffers_.pop_back();
1530 input_record.at_device = true;
1531 input_record.mfc_output = mfc_buffer;
1532 output_record.bytes_used[0] = 0;
1533 output_record.bytes_used[1] = 0;
1534 gsc_input_buffer_queued_count_++;
1535 DVLOG(3) << "EnqueueGscInputRecord(): enqueued input_id="
1536 << output_record.input_id;
1540 bool ExynosVideoDecodeAccelerator::EnqueueGscOutputRecord() {
1541 DVLOG(3) << "EnqueueGscOutputRecord()";
1542 DCHECK(!gsc_free_output_buffers_.empty());
1544 // Enqueue a GSC output (VIDEO_CAPTURE) buffer.
1545 const int buffer = gsc_free_output_buffers_.front();
1546 GscOutputRecord& output_record = gsc_output_buffer_map_[buffer];
1547 DCHECK(!output_record.at_device);
1548 DCHECK(!output_record.at_client);
1549 if (output_record.egl_sync != EGL_NO_SYNC_KHR) {
1552 "EVDA::EnqueueGscOutputRecord: eglClientWaitSyncKHR");
1553 // If we have to wait for completion, wait. Note that
1554 // gsc_free_output_buffers_ is a FIFO queue, so we always wait on the
1555 // buffer that has been in the queue the longest.
1556 eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0,
1558 eglDestroySyncKHR(egl_display_, output_record.egl_sync);
1559 output_record.egl_sync = EGL_NO_SYNC_KHR;
1561 struct v4l2_buffer qbuf;
1562 struct v4l2_plane qbuf_plane;
1563 memset(&qbuf, 0, sizeof(qbuf));
1564 memset(&qbuf_plane, 0, sizeof(qbuf_plane));
1565 qbuf.index = buffer;
1566 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1567 qbuf.memory = V4L2_MEMORY_DMABUF;
1568 qbuf.m.planes = &qbuf_plane;
1569 qbuf.m.planes[0].m.fd = output_record.fd;
1571 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QBUF, &qbuf);
1572 gsc_free_output_buffers_.pop_front();
1573 output_record.at_device = true;
1574 gsc_output_buffer_queued_count_++;
1578 void ExynosVideoDecodeAccelerator::ReusePictureBufferTask(
1579 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) {
1580 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id="
1581 << picture_buffer_id;
1582 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1583 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask");
1585 // We run ReusePictureBufferTask even if we're in kResetting.
1586 if (decoder_state_ == kError) {
1587 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state";
1591 if (decoder_state_ == kChangingResolution) {
1592 DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution";
1597 for (index = 0; index < gsc_output_buffer_map_.size(); ++index)
1598 if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id)
1601 if (index >= gsc_output_buffer_map_.size()) {
1602 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found";
1603 NOTIFY_ERROR(INVALID_ARGUMENT);
1607 GscOutputRecord& output_record = gsc_output_buffer_map_[index];
1608 if (output_record.at_device || !output_record.at_client) {
1609 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable";
1610 NOTIFY_ERROR(INVALID_ARGUMENT);
1614 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1615 output_record.at_client = false;
1616 output_record.egl_sync = egl_sync_ref->egl_sync;
1617 gsc_free_output_buffers_.push_back(index);
1618 decoder_frames_at_client_--;
1619 // Take ownership of the EGLSync.
1620 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR;
1621 // We got a buffer back, so kick the GSC.
1625 void ExynosVideoDecodeAccelerator::FlushTask() {
1626 DVLOG(3) << "FlushTask()";
1627 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1628 TRACE_EVENT0("Video Decoder", "EVDA::FlushTask");
1630 // Flush outstanding buffers.
1631 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) {
1632 // There's nothing in the pipe, so return done immediately.
1633 DVLOG(3) << "FlushTask(): returning flush";
1634 child_message_loop_proxy_->PostTask(
1635 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_));
1637 } else if (decoder_state_ == kError) {
1638 DVLOG(2) << "FlushTask(): early out: kError state";
1642 // We don't support stacked flushing.
1643 DCHECK(!decoder_flushing_);
1645 // Queue up an empty buffer -- this triggers the flush.
1646 decoder_input_queue_.push_back(linked_ptr<BitstreamBufferRef>(
1647 new BitstreamBufferRef(io_client_, io_message_loop_proxy_, NULL, 0,
1649 decoder_flushing_ = true;
1650 SendPictureReady(); // Send all pending PictureReady.
1652 ScheduleDecodeBufferTaskIfNeeded();
1655 void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
1656 if (!decoder_flushing_)
1659 // Pipeline is empty when:
1660 // * Decoder input queue is empty of non-delayed buffers.
1661 // * There is no currently filling input buffer.
1662 // * MFC input holding queue is empty.
1663 // * All MFC input (VIDEO_OUTPUT) buffers are returned.
1664 // * MFC -> GSC holding queue is empty.
1665 // * All GSC input (VIDEO_OUTPUT) buffers are returned.
1666 if (!decoder_input_queue_.empty()) {
1667 if (decoder_input_queue_.front()->input_id !=
1668 decoder_delay_bitstream_buffer_id_)
1671 if (decoder_current_input_buffer_ != -1)
1673 if ((mfc_input_ready_queue_.size() +
1674 mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() +
1675 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0)
1678 // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon
1679 // sequence after flush to continue, even if we are not resetting. This would
1680 // make sense, because we don't really want to resume from a non-resume point
1681 // (e.g. not from an IDR) if we are flushed.
1682 // MSE player however triggers a Flush() on chunk end, but never Reset(). One
1683 // could argue either way, or even say that Flush() is not needed/harmful when
1684 // transitioning to next chunk.
1685 // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when
1686 // doing MSE. This should be harmless otherwise.
1687 if (!StopDevicePoll(false))
1690 if (!StartDevicePoll())
1693 decoder_delay_bitstream_buffer_id_ = -1;
1694 decoder_flushing_ = false;
1695 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush";
1696 child_message_loop_proxy_->PostTask(
1697 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_));
1699 // While we were flushing, we early-outed DecodeBufferTask()s.
1700 ScheduleDecodeBufferTaskIfNeeded();
1703 void ExynosVideoDecodeAccelerator::ResetTask() {
1704 DVLOG(3) << "ResetTask()";
1705 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1706 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask");
1708 if (decoder_state_ == kError) {
1709 DVLOG(2) << "ResetTask(): early out: kError state";
1713 // If we are in the middle of switching resolutions, postpone reset until
1714 // it's done. We don't have to worry about timing of this wrt to decoding,
1715 // because MFC input pipe is already stopped if we are changing resolution.
1716 // We will come back here after we are done with the resolution change.
1717 DCHECK(!resolution_change_reset_pending_);
1718 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) {
1719 resolution_change_reset_pending_ = true;
1723 // We stop streaming and clear buffer tracking info (not preserving
1725 // StopDevicePoll() unconditionally does _not_ destroy buffers, however.
1726 if (!StopDevicePoll(false))
1731 resolution_change_pending_ = false;
1732 decoder_current_bitstream_buffer_.reset();
1733 decoder_input_queue_.clear();
1735 decoder_current_input_buffer_ = -1;
1737 // If we were flushing, we'll never return any more BitstreamBuffers or
1738 // PictureBuffers; they have all been dropped and returned by now.
1739 NotifyFlushDoneIfNeeded();
1741 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening
1742 // jobs will early-out in the kResetting state.
1743 decoder_state_ = kResetting;
1744 SendPictureReady(); // Send all pending PictureReady.
1745 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1746 &ExynosVideoDecodeAccelerator::ResetDoneTask, base::Unretained(this)));
1749 void ExynosVideoDecodeAccelerator::ResetDoneTask() {
1750 DVLOG(3) << "ResetDoneTask()";
1751 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1752 TRACE_EVENT0("Video Decoder", "EVDA::ResetDoneTask");
1754 if (decoder_state_ == kError) {
1755 DVLOG(2) << "ResetDoneTask(): early out: kError state";
1759 // Reset format-specific bits.
1760 if (video_profile_ >= media::H264PROFILE_MIN &&
1761 video_profile_ <= media::H264PROFILE_MAX) {
1762 decoder_h264_parser_.reset(new content::H264Parser());
1765 // Jobs drained, we're finished resetting.
1766 DCHECK_EQ(decoder_state_, kResetting);
1767 decoder_state_ = kAfterReset;
1768 decoder_partial_frame_pending_ = false;
1769 decoder_delay_bitstream_buffer_id_ = -1;
1770 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
1771 &Client::NotifyResetDone, client_));
1773 // While we were resetting, we early-outed DecodeBufferTask()s.
1774 ScheduleDecodeBufferTaskIfNeeded();
1777 void ExynosVideoDecodeAccelerator::DestroyTask() {
1778 DVLOG(3) << "DestroyTask()";
1779 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask");
1781 // DestroyTask() should run regardless of decoder_state_.
1783 // Stop streaming and the device_poll_thread_.
1784 StopDevicePoll(false);
1786 decoder_current_bitstream_buffer_.reset();
1787 decoder_current_input_buffer_ = -1;
1788 decoder_decode_buffer_tasks_scheduled_ = 0;
1789 decoder_frames_at_client_ = 0;
1790 decoder_input_queue_.clear();
1791 decoder_flushing_ = false;
1793 // Set our state to kError. Just in case.
1794 decoder_state_ = kError;
1797 bool ExynosVideoDecodeAccelerator::StartDevicePoll() {
1798 DVLOG(3) << "StartDevicePoll()";
1799 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1800 DCHECK(!device_poll_thread_.IsRunning());
1802 // Start up the device poll thread and schedule its first DevicePollTask().
1803 if (!device_poll_thread_.Start()) {
1804 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
1805 NOTIFY_ERROR(PLATFORM_FAILURE);
1808 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1809 &ExynosVideoDecodeAccelerator::DevicePollTask,
1810 base::Unretained(this),
1816 bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) {
1817 DVLOG(3) << "StopDevicePoll()";
1818 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1820 // Signal the DevicePollTask() to stop, and stop the device poll thread.
1821 if (!SetDevicePollInterrupt())
1823 device_poll_thread_.Stop();
1824 // Clear the interrupt now, to be sure.
1825 if (!ClearDevicePollInterrupt())
1829 if (!keep_mfc_input_state) {
1830 if (mfc_input_streamon_) {
1831 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1832 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
1834 mfc_input_streamon_ = false;
1836 if (mfc_output_streamon_) {
1837 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1838 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
1840 mfc_output_streamon_ = false;
1841 if (gsc_input_streamon_) {
1842 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1843 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type);
1845 gsc_input_streamon_ = false;
1846 if (gsc_output_streamon_) {
1847 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1848 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type);
1850 gsc_output_streamon_ = false;
1852 // Reset all our accounting info.
1853 if (!keep_mfc_input_state) {
1854 mfc_input_ready_queue_.clear();
1855 mfc_free_input_buffers_.clear();
1856 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
1857 mfc_free_input_buffers_.push_back(i);
1858 mfc_input_buffer_map_[i].at_device = false;
1859 mfc_input_buffer_map_[i].bytes_used = 0;
1860 mfc_input_buffer_map_[i].input_id = -1;
1862 mfc_input_buffer_queued_count_ = 0;
1864 mfc_free_output_buffers_.clear();
1865 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
1866 mfc_free_output_buffers_.push_back(i);
1867 mfc_output_buffer_map_[i].at_device = false;
1868 mfc_output_buffer_map_[i].input_id = -1;
1870 mfc_output_buffer_queued_count_ = 0;
1871 mfc_output_gsc_input_queue_.clear();
1872 gsc_free_input_buffers_.clear();
1873 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) {
1874 gsc_free_input_buffers_.push_back(i);
1875 gsc_input_buffer_map_[i].at_device = false;
1876 gsc_input_buffer_map_[i].mfc_output = -1;
1878 gsc_input_buffer_queued_count_ = 0;
1879 gsc_free_output_buffers_.clear();
1880 for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) {
1881 // Only mark those free that aren't being held by the VDA.
1882 if (!gsc_output_buffer_map_[i].at_client) {
1883 gsc_free_output_buffers_.push_back(i);
1884 gsc_output_buffer_map_[i].at_device = false;
1887 gsc_output_buffer_queued_count_ = 0;
1889 DVLOG(3) << "StopDevicePoll(): device poll stopped";
1893 bool ExynosVideoDecodeAccelerator::SetDevicePollInterrupt() {
1894 DVLOG(3) << "SetDevicePollInterrupt()";
1895 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1897 const uint64 buf = 1;
1898 if (HANDLE_EINTR(write(device_poll_interrupt_fd_, &buf, sizeof(buf))) == -1) {
1899 DPLOG(ERROR) << "SetDevicePollInterrupt(): write() failed";
1900 NOTIFY_ERROR(PLATFORM_FAILURE);
1906 bool ExynosVideoDecodeAccelerator::ClearDevicePollInterrupt() {
1907 DVLOG(3) << "ClearDevicePollInterrupt()";
1908 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1911 if (HANDLE_EINTR(read(device_poll_interrupt_fd_, &buf, sizeof(buf))) == -1) {
1912 if (errno == EAGAIN) {
1913 // No interrupt flag set, and we're reading nonblocking. Not an error.
1916 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed";
1917 NOTIFY_ERROR(PLATFORM_FAILURE);
1924 void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
1925 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1926 DCHECK_EQ(decoder_state_, kDecoding);
1928 if (!resolution_change_pending_)
1931 if (!mfc_output_gsc_input_queue_.empty() ||
1932 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) {
1933 DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish.";
1937 DVLOG(3) << "No more work for GSC, initiate resolution change";
1939 // Keep MFC input queue.
1940 if (!StopDevicePoll(true))
1943 decoder_state_ = kChangingResolution;
1944 DCHECK(resolution_change_pending_);
1945 resolution_change_pending_ = false;
1947 // Post a task to clean up buffers on child thread. This will also ensure
1948 // that we won't accept ReusePictureBuffer() anymore after that.
1949 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
1950 &ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers,
1954 void ExynosVideoDecodeAccelerator::FinishResolutionChange() {
1955 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1956 DVLOG(3) << "FinishResolutionChange()";
1958 if (decoder_state_ == kError) {
1959 DVLOG(2) << "FinishResolutionChange(): early out: kError state";
1963 struct v4l2_format format;
1965 bool ret = GetFormatInfo(&format, &again);
1966 if (!ret || again) {
1967 DVLOG(3) << "Couldn't get format information after resolution change";
1968 NOTIFY_ERROR(PLATFORM_FAILURE);
1972 if (!CreateBuffersForFormat(format)) {
1973 DVLOG(3) << "Couldn't reallocate buffers after resolution change";
1974 NOTIFY_ERROR(PLATFORM_FAILURE);
1978 // From here we stay in kChangingResolution and wait for
1979 // AssignPictureBuffers() before we can resume.
1982 void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() {
1983 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1984 DVLOG(3) << "ResumeAfterResolutionChange()";
1986 decoder_state_ = kDecoding;
1988 if (resolution_change_reset_pending_) {
1989 resolution_change_reset_pending_ = false;
1994 if (!StartDevicePoll())
1998 // Gsc will get enqueued in AssignPictureBuffersTask().
1999 ScheduleDecodeBufferTaskIfNeeded();
2002 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) {
2003 DVLOG(3) << "DevicePollTask()";
2004 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current());
2005 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask");
2007 // This routine just polls the set of device fds, and schedules a
2008 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur.
2009 // Other threads may notify this task to return early by writing to
2010 // device_poll_interrupt_fd_.
2011 struct pollfd pollfds[3];
2013 int mfc_pollfd = -1;
2015 // Add device_poll_interrupt_fd_;
2016 pollfds[0].fd = device_poll_interrupt_fd_;
2017 pollfds[0].events = POLLIN | POLLERR;
2020 if (poll_fds & kPollMfc) {
2021 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set";
2022 pollfds[nfds].fd = mfc_fd_;
2023 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI;
2027 // Add GSC fd, if we should poll on it.
2028 // GSC has to wait until both input and output buffers are queued.
2029 if (poll_fds & kPollGsc) {
2030 DVLOG(3) << "DevicePollTask(): adding GSC to poll() set";
2031 pollfds[nfds].fd = gsc_fd_;
2032 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR;
2037 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) {
2038 DPLOG(ERROR) << "DevicePollTask(): poll() failed";
2039 NOTIFY_ERROR(PLATFORM_FAILURE);
2043 bool mfc_event_pending = (mfc_pollfd != -1 &&
2044 pollfds[mfc_pollfd].revents & POLLPRI);
2046 // All processing should happen on ServiceDeviceTask(), since we shouldn't
2047 // touch decoder state from this thread.
2048 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
2049 &ExynosVideoDecodeAccelerator::ServiceDeviceTask,
2050 base::Unretained(this), mfc_event_pending));
2053 void ExynosVideoDecodeAccelerator::NotifyError(Error error) {
2054 DVLOG(2) << "NotifyError()";
2056 if (!child_message_loop_proxy_->BelongsToCurrentThread()) {
2057 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
2058 &ExynosVideoDecodeAccelerator::NotifyError, weak_this_, error));
2063 client_->NotifyError(error);
2064 client_ptr_factory_.InvalidateWeakPtrs();
2068 void ExynosVideoDecodeAccelerator::SetDecoderState(State state) {
2069 DVLOG(3) << "SetDecoderState(): state=" << state;
2071 // We can touch decoder_state_ only if this is the decoder thread or the
2072 // decoder thread isn't running.
2073 if (decoder_thread_.message_loop() != NULL &&
2074 decoder_thread_.message_loop() != base::MessageLoop::current()) {
2075 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
2076 &ExynosVideoDecodeAccelerator::SetDecoderState,
2077 base::Unretained(this), state));
2079 decoder_state_ = state;
2083 bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
2085 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2088 memset(format, 0, sizeof(*format));
2089 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2090 if (HANDLE_EINTR(ioctl(mfc_fd_, VIDIOC_G_FMT, format)) != 0) {
2091 if (errno == EINVAL) {
2092 // EINVAL means we haven't seen sufficient stream to decode the format.
2096 DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
2097 NOTIFY_ERROR(PLATFORM_FAILURE);
2105 bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat(
2106 const struct v4l2_format& format) {
2107 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2108 CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
2109 frame_buffer_size_.SetSize(
2110 format.fmt.pix_mp.width, format.fmt.pix_mp.height);
2111 mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
2112 mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
2113 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
2114 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
2115 DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
2116 << frame_buffer_size_.ToString();
2118 if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
2119 !CreateGscOutputBuffers())
2125 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() {
2126 DVLOG(3) << "CreateMfcInputBuffers()";
2127 // We always run this as we prepare to initialize.
2128 DCHECK_EQ(decoder_state_, kUninitialized);
2129 DCHECK(!mfc_input_streamon_);
2130 DCHECK(mfc_input_buffer_map_.empty());
2132 __u32 pixelformat = 0;
2133 if (video_profile_ >= media::H264PROFILE_MIN &&
2134 video_profile_ <= media::H264PROFILE_MAX) {
2135 pixelformat = V4L2_PIX_FMT_H264;
2136 } else if (video_profile_ >= media::VP8PROFILE_MIN &&
2137 video_profile_ <= media::VP8PROFILE_MAX) {
2138 pixelformat = V4L2_PIX_FMT_VP8;
2143 struct v4l2_format format;
2144 memset(&format, 0, sizeof(format));
2145 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2146 format.fmt.pix_mp.pixelformat = pixelformat;
2147 format.fmt.pix_mp.plane_fmt[0].sizeimage = kMfcInputBufferMaxSize;
2148 format.fmt.pix_mp.num_planes = 1;
2149 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format);
2151 struct v4l2_requestbuffers reqbufs;
2152 memset(&reqbufs, 0, sizeof(reqbufs));
2153 reqbufs.count = kMfcInputBufferCount;
2154 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2155 reqbufs.memory = V4L2_MEMORY_MMAP;
2156 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs);
2157 mfc_input_buffer_map_.resize(reqbufs.count);
2158 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
2159 mfc_free_input_buffers_.push_back(i);
2161 // Query for the MEMORY_MMAP pointer.
2162 struct v4l2_plane planes[1];
2163 struct v4l2_buffer buffer;
2164 memset(&buffer, 0, sizeof(buffer));
2165 memset(planes, 0, sizeof(planes));
2167 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2168 buffer.memory = V4L2_MEMORY_MMAP;
2169 buffer.m.planes = planes;
2171 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYBUF, &buffer);
2172 void* address = mmap(NULL, buffer.m.planes[0].length,
2173 PROT_READ | PROT_WRITE, MAP_SHARED, mfc_fd_,
2174 buffer.m.planes[0].m.mem_offset);
2175 if (address == MAP_FAILED) {
2176 DPLOG(ERROR) << "CreateMfcInputBuffers(): mmap() failed";
2179 mfc_input_buffer_map_[i].address = address;
2180 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length;
2186 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() {
2187 DVLOG(3) << "CreateMfcOutputBuffers()";
2188 DCHECK(decoder_state_ == kInitialized ||
2189 decoder_state_ == kChangingResolution);
2190 DCHECK(!mfc_output_streamon_);
2191 DCHECK(mfc_output_buffer_map_.empty());
2193 // Number of MFC output buffers we need.
2194 struct v4l2_control ctrl;
2195 memset(&ctrl, 0, sizeof(ctrl));
2196 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
2197 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl);
2198 mfc_output_dpb_size_ = ctrl.value;
2200 // Output format setup in Initialize().
2202 // Allocate the output buffers.
2203 struct v4l2_requestbuffers reqbufs;
2204 memset(&reqbufs, 0, sizeof(reqbufs));
2205 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount;
2206 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2207 reqbufs.memory = V4L2_MEMORY_MMAP;
2208 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs);
2210 // Fill our free-buffers list, and create DMABUFs from them.
2211 mfc_output_buffer_map_.resize(reqbufs.count);
2212 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
2213 mfc_free_output_buffers_.push_back(i);
2215 // Query for the MEMORY_MMAP pointer.
2216 struct v4l2_plane planes[2];
2217 struct v4l2_buffer buffer;
2218 memset(&buffer, 0, sizeof(buffer));
2219 memset(planes, 0, sizeof(planes));
2221 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2222 buffer.memory = V4L2_MEMORY_MMAP;
2223 buffer.m.planes = planes;
2225 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYBUF, &buffer);
2227 // Get their user memory for GSC input.
2228 for (int j = 0; j < 2; ++j) {
2229 void* address = mmap(NULL, buffer.m.planes[j].length,
2230 PROT_READ | PROT_WRITE, MAP_SHARED, mfc_fd_,
2231 buffer.m.planes[j].m.mem_offset);
2232 if (address == MAP_FAILED) {
2233 DPLOG(ERROR) << "CreateMfcInputBuffers(): mmap() failed";
2236 mfc_output_buffer_map_[i].address[j] = address;
2237 mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length;
2244 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() {
2245 DVLOG(3) << "CreateGscInputBuffers()";
2246 DCHECK(decoder_state_ == kInitialized ||
2247 decoder_state_ == kChangingResolution);
2248 DCHECK(!gsc_input_streamon_);
2249 DCHECK(gsc_input_buffer_map_.empty());
2251 struct v4l2_format format;
2252 memset(&format, 0, sizeof(format));
2253 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2254 format.fmt.pix_mp.width = frame_buffer_size_.width();
2255 format.fmt.pix_mp.height = frame_buffer_size_.height();
2256 format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_;
2257 format.fmt.pix_mp.plane_fmt[0].sizeimage = mfc_output_buffer_size_[0];
2258 format.fmt.pix_mp.plane_fmt[1].sizeimage = mfc_output_buffer_size_[1];
2259 // NV12MT_16X16 is a tiled format for which bytesperline doesn't make too much
2260 // sense. Convention seems to be to assume 8bpp for these tiled formats.
2261 format.fmt.pix_mp.plane_fmt[0].bytesperline = frame_buffer_size_.width();
2262 format.fmt.pix_mp.plane_fmt[1].bytesperline = frame_buffer_size_.width();
2263 format.fmt.pix_mp.num_planes = 2;
2264 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_FMT, &format);
2266 struct v4l2_control control;
2267 memset(&control, 0, sizeof(control));
2268 control.id = V4L2_CID_ROTATE;
2270 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
2272 memset(&control, 0, sizeof(control));
2273 control.id = V4L2_CID_HFLIP;
2275 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
2277 memset(&control, 0, sizeof(control));
2278 control.id = V4L2_CID_VFLIP;
2280 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
2282 memset(&control, 0, sizeof(control));
2283 control.id = V4L2_CID_GLOBAL_ALPHA;
2284 control.value = 255;
2285 if (HANDLE_EINTR(ioctl(gsc_fd_, VIDIOC_S_CTRL, &control)) != 0) {
2286 memset(&control, 0, sizeof(control));
2287 control.id = V4L2_CID_ALPHA_COMPONENT;
2288 control.value = 255;
2289 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
2292 struct v4l2_requestbuffers reqbufs;
2293 memset(&reqbufs, 0, sizeof(reqbufs));
2294 reqbufs.count = kGscInputBufferCount;
2295 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2296 reqbufs.memory = V4L2_MEMORY_USERPTR;
2297 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs);
2299 gsc_input_buffer_map_.resize(reqbufs.count);
2300 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) {
2301 gsc_free_input_buffers_.push_back(i);
2302 gsc_input_buffer_map_[i].mfc_output = -1;
2308 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() {
2309 DVLOG(3) << "CreateGscOutputBuffers()";
2310 DCHECK(decoder_state_ == kInitialized ||
2311 decoder_state_ == kChangingResolution);
2312 DCHECK(!gsc_output_streamon_);
2313 DCHECK(gsc_output_buffer_map_.empty());
2315 // GSC outputs into the EGLImages we create from the textures we are
2316 // assigned. Assume RGBA8888 format.
2317 struct v4l2_format format;
2318 memset(&format, 0, sizeof(format));
2319 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2320 format.fmt.pix_mp.width = frame_buffer_size_.width();
2321 format.fmt.pix_mp.height = frame_buffer_size_.height();
2322 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB32;
2323 format.fmt.pix_mp.plane_fmt[0].sizeimage =
2324 frame_buffer_size_.width() * frame_buffer_size_.height() * 4;
2325 format.fmt.pix_mp.plane_fmt[0].bytesperline = frame_buffer_size_.width() * 4;
2326 format.fmt.pix_mp.num_planes = 1;
2327 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_FMT, &format);
2329 struct v4l2_requestbuffers reqbufs;
2330 memset(&reqbufs, 0, sizeof(reqbufs));
2331 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount;
2332 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2333 reqbufs.memory = V4L2_MEMORY_DMABUF;
2334 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs);
2336 // We don't actually fill in the freelist or the map here. That happens once
2337 // we have actual usable buffers, after AssignPictureBuffers();
2338 gsc_output_buffer_map_.resize(reqbufs.count);
2340 DVLOG(3) << "CreateGscOutputBuffers(): ProvidePictureBuffers(): "
2341 << "buffer_count=" << gsc_output_buffer_map_.size()
2342 << ", width=" << frame_buffer_size_.width()
2343 << ", height=" << frame_buffer_size_.height();
2344 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
2345 &Client::ProvidePictureBuffers, client_, gsc_output_buffer_map_.size(),
2346 gfx::Size(frame_buffer_size_.width(), frame_buffer_size_.height()),
2352 void ExynosVideoDecodeAccelerator::DestroyMfcInputBuffers() {
2353 DVLOG(3) << "DestroyMfcInputBuffers()";
2354 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
2355 DCHECK(!mfc_input_streamon_);
2357 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
2358 if (mfc_input_buffer_map_[i].address != NULL) {
2359 munmap(mfc_input_buffer_map_[i].address,
2360 mfc_input_buffer_map_[i].length);
2364 struct v4l2_requestbuffers reqbufs;
2365 memset(&reqbufs, 0, sizeof(reqbufs));
2367 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2368 reqbufs.memory = V4L2_MEMORY_MMAP;
2369 if (ioctl(mfc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
2370 DPLOG(ERROR) << "DestroyMfcInputBuffers(): ioctl() failed: VIDIOC_REQBUFS";
2372 mfc_input_buffer_map_.clear();
2373 mfc_free_input_buffers_.clear();
2376 void ExynosVideoDecodeAccelerator::DestroyMfcOutputBuffers() {
2377 DVLOG(3) << "DestroyMfcOutputBuffers()";
2378 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
2379 DCHECK(!mfc_output_streamon_);
2381 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
2382 if (mfc_output_buffer_map_[i].address[0] != NULL)
2383 munmap(mfc_output_buffer_map_[i].address[0],
2384 mfc_output_buffer_map_[i].length[0]);
2385 if (mfc_output_buffer_map_[i].address[1] != NULL)
2386 munmap(mfc_output_buffer_map_[i].address[1],
2387 mfc_output_buffer_map_[i].length[1]);
2390 struct v4l2_requestbuffers reqbufs;
2391 memset(&reqbufs, 0, sizeof(reqbufs));
2393 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2394 reqbufs.memory = V4L2_MEMORY_MMAP;
2395 if (ioctl(mfc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
2396 DPLOG(ERROR) << "DestroyMfcOutputBuffers() ioctl() failed: VIDIOC_REQBUFS";
2398 mfc_output_buffer_map_.clear();
2399 mfc_free_output_buffers_.clear();
2402 void ExynosVideoDecodeAccelerator::DestroyGscInputBuffers() {
2403 DVLOG(3) << "DestroyGscInputBuffers()";
2404 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
2405 DCHECK(!gsc_input_streamon_);
2407 struct v4l2_requestbuffers reqbufs;
2408 memset(&reqbufs, 0, sizeof(reqbufs));
2410 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2411 reqbufs.memory = V4L2_MEMORY_DMABUF;
2412 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
2413 DPLOG(ERROR) << "DestroyGscInputBuffers(): ioctl() failed: VIDIOC_REQBUFS";
2415 gsc_input_buffer_map_.clear();
2416 gsc_free_input_buffers_.clear();
2419 void ExynosVideoDecodeAccelerator::DestroyGscOutputBuffers() {
2420 DVLOG(3) << "DestroyGscOutputBuffers()";
2421 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
2422 DCHECK(!gsc_output_streamon_);
2424 if (gsc_output_buffer_map_.size() != 0) {
2425 if (!make_context_current_.Run())
2426 DLOG(ERROR) << "DestroyGscOutputBuffers(): "
2427 << "could not make context current";
2431 GscOutputRecord& output_record = gsc_output_buffer_map_[i];
2432 if (output_record.fd != -1)
2433 HANDLE_EINTR(close(output_record.fd));
2434 if (output_record.egl_image != EGL_NO_IMAGE_KHR)
2435 eglDestroyImageKHR(egl_display_, output_record.egl_image);
2436 if (output_record.egl_sync != EGL_NO_SYNC_KHR)
2437 eglDestroySyncKHR(egl_display_, output_record.egl_sync);
2439 DVLOG(1) << "DestroyGscOutputBuffers(): "
2440 << "dismissing PictureBuffer id=" << output_record.picture_id;
2441 client_->DismissPictureBuffer(output_record.picture_id);
2444 } while (i < gsc_output_buffer_map_.size());
2447 struct v4l2_requestbuffers reqbufs;
2448 memset(&reqbufs, 0, sizeof(reqbufs));
2450 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2451 reqbufs.memory = V4L2_MEMORY_DMABUF;
2452 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
2453 DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS";
2455 gsc_output_buffer_map_.clear();
2456 gsc_free_output_buffers_.clear();
2459 void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
2460 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
2461 DVLOG(3) << "ResolutionChangeDestroyBuffers()";
2463 DestroyGscInputBuffers();
2464 DestroyGscOutputBuffers();
2465 DestroyMfcOutputBuffers();
2467 // Finish resolution change on decoder thread.
2468 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
2469 &ExynosVideoDecodeAccelerator::FinishResolutionChange,
2470 base::Unretained(this)));
2473 void ExynosVideoDecodeAccelerator::SendPictureReady() {
2474 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2475 bool resetting_or_flushing =
2476 (decoder_state_ == kResetting || decoder_flushing_);
2477 while (pending_picture_ready_.size() > 0) {
2478 bool cleared = pending_picture_ready_.front().cleared;
2479 const media::Picture& picture = pending_picture_ready_.front().picture;
2480 if (cleared && picture_clearing_count_ == 0) {
2481 // This picture is cleared. Post it to IO thread to reduce latency. This
2482 // should be the case after all pictures are cleared at the beginning.
2483 io_message_loop_proxy_->PostTask(
2484 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture));
2485 pending_picture_ready_.pop();
2486 } else if (!cleared || resetting_or_flushing) {
2487 DVLOG(3) << "SendPictureReady()"
2488 << ". cleared=" << pending_picture_ready_.front().cleared
2489 << ", decoder_state_=" << decoder_state_
2490 << ", decoder_flushing_=" << decoder_flushing_
2491 << ", picture_clearing_count_=" << picture_clearing_count_;
2492 // If the picture is not cleared, post it to the child thread because it
2493 // has to be cleared in the child thread. A picture only needs to be
2494 // cleared once. If the decoder is resetting or flushing, send all
2495 // pictures to ensure PictureReady arrive before reset or flush done.
2496 child_message_loop_proxy_->PostTaskAndReply(
2498 base::Bind(&Client::PictureReady, client_, picture),
2499 // Unretained is safe. If Client::PictureReady gets to run, |this| is
2500 // alive. Destroy() will wait the decode thread to finish.
2501 base::Bind(&ExynosVideoDecodeAccelerator::PictureCleared,
2502 base::Unretained(this)));
2503 picture_clearing_count_++;
2504 pending_picture_ready_.pop();
2506 // This picture is cleared. But some pictures are about to be cleared on
2507 // the child thread. To preserve the order, do not send this until those
2508 // pictures are cleared.
2514 void ExynosVideoDecodeAccelerator::PictureCleared() {
2515 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
2516 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2517 DCHECK_GT(picture_clearing_count_, 0);
2518 picture_clearing_count_--;
2522 } // namespace content