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

Unified Diff: content/common/gpu/media/exynos_video_encode_accelerator.h

Issue 16693005: Add ExynosVideoEncodeAccelerator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@screencast_cl_5
Patch Set: b673f1a3 WIP - for posciak@ Created 7 years, 5 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/exynos_video_encode_accelerator.h
diff --git a/content/common/gpu/media/exynos_video_encode_accelerator.h b/content/common/gpu/media/exynos_video_encode_accelerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..75b97b6621bfa12fd6d324271c28ae058787adf5
--- /dev/null
+++ b/content/common/gpu/media/exynos_video_encode_accelerator.h
@@ -0,0 +1,360 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_
+#define CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_
+
+#include <list>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
+#include "content/common/gpu/gl_surface_encoder.h"
+#include "media/base/video_decoder_config.h"
+#include "media/video/video_encode_accelerator.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace base {
+
+class MessageLoopProxy;
+
+} // namespace base
+
+namespace gfx {
+
+class GLSurface;
+
+} // namespace gfx
+
+namespace media {
+
+class BitstreamBuffer;
+
+} // namespace media
+
+namespace content {
+
+// This class handles Exynos video encode acceleration by interfacing with the
+// V4L2 devices exported by the Multi Format Codec and GScaler hardware blocks
+// on the Exynos platform.
+//
+// The threading model of this class is the same as the
+// ExynosVideoDecodeAccelerator (from which class this was designed). The one
+// notable difference is in the thread "ownership" of the GSC free input buffers
+// queue (gsc_free_input_buffers_). As this queue needs to be queried and
+// dequeued from the child thread (to obtain a texture to copy the backbuffer
+// to in Encode()), it is owned by the child thread.
+class ExynosVideoEncodeAccelerator : public media::VideoEncodeAccelerator {
+ public:
+ ExynosVideoEncodeAccelerator(
+ EGLDisplay egl_display,
+ media::VideoEncodeAccelerator::Client* client,
+ const base::Callback<bool(void)>& make_context_current,
+ bool encode_from_backbuffer);
+ ~ExynosVideoEncodeAccelerator();
+
+ // media::VideoEncodeAccelerator implementation.
+ virtual void Initialize(media::VideoCodecProfile profile,
+ const gfx::Size& input_resolution,
+ const gfx::Size& output_resolution,
+ int32 initial_bitrate) OVERRIDE;
+ virtual void Encode(
+ const scoped_refptr<media::VideoFrame>& frame,
+ int32 frame_id,
+ bool force_keyframe) OVERRIDE;
+ virtual void UseBitstreamBuffer(
+ const media::BitstreamBuffer& buffer) OVERRIDE;
+ virtual void RequestEncodingParameterChange(int32 bitrate) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+
+ private:
+ // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed as
+ // input to UseBitstreamBuffer.
+ struct BitstreamBufferRef;
+
+ // Record for GSC input buffers.
+ struct GscInputRecord {
+ GscInputRecord();
+ bool at_device;
+ int frame_id;
+ EGLSyncKHR egl_sync;
+ EGLImageKHR egl_image;
+ GLuint texture_id;
+ void* address;
+ size_t length;
+ };
+
+ // Record for GSC output buffers.
+ struct GscOutputRecord {
+ GscOutputRecord();
+ bool at_device;
+ int mfc_input;
+ void* address[3];
+ size_t length[3];
+ size_t bytes_used[3];
+ };
+
+ // Record for MFC input buffers.
+ struct MfcInputRecord {
+ MfcInputRecord();
+ bool at_device;
+ int fd[2];
+ };
+
+ // Record for MFC output buffers.
+ struct MfcOutputRecord {
+ MfcOutputRecord();
+ bool at_device;
+ void* address;
+ size_t length;
+ size_t bytes_used;
+ };
+
+ enum {
+ // These are rather subjectively tuned.
+ kGscInputBufferCount = 2,
+ kGscOutputBufferCount = 2,
+ kMfcOutputBufferCount = 3,
+ // MFC hardware does not report required output buffer size correctly.
+ // Use maximum theoretical size to avoid hanging the hardware.
+ kMfcOutputBufferSize = (2 * 1024 * 1024),
+ };
+
+ // Internal state of the encoder.
+ enum State {
+ kUninitialized, // Initialize() not yet called.
+ kInitialized, // Initialize() returned true; ready to start decoding.
+ kEncoding, // Encoding frames.
+ kError, // Error in kEncoding state.
+ };
+
+ // File descriptors we need to poll.
+ enum PollFds {
+ kPollGsc = (1 << 0),
+ kPollMfc = (1 << 1),
+ };
+
+ //
+ // Child thread utility functions, supporting API entry points.
+ //
+
+ // Return a buffer to gsc_free_input_buffers_.
+ void ReturnFreeGscInputBuffer(int index);
+
+ //
+ // Decoding tasks, to be run on encode_thread_.
+ //
+
+ // Encode a GSC input buffer.
+ void EncodeTask(int gsc_input_index);
+
+ // Copy a media::VideoFrame to the GSC input buffer, then encode it.
+ void CopyFrameAndEncodeTask(const scoped_refptr<media::VideoFrame>& frame,
+ int gsc_input_index);
+
+ // Add a BitstreamBuffer to out queue of buffers ready to be used for client
+ // output.
+ void UseBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref);
+
+ // Device destruction task.
+ void DestroyTask();
+
+ // Service I/O on the V4L2 devices. This task should only be scheduled from
+ // DevicePollTask().
+ void ServiceDeviceTask();
+ // Handle the various device queues.
+ void EnqueueGsc();
+ void DequeueGsc();
+ void EnqueueMfc();
+ void DequeueMfc();
+ // Enqueue a buffer on the corresponding queue.
+ bool EnqueueGscInputRecord();
+ bool EnqueueGscOutputRecord();
+ bool EnqueueMfcInputRecord();
+ bool EnqueueMfcOutputRecord();
+ // Return completed buffers to the client.
+ void ReturnCompleteBuffers();
+
+ // Attempt to start/stop device_poll_thread_.
+ bool StartDevicePoll();
+ bool StopDevicePoll();
+ // Set/clear the device poll interrupt (using device_ooll_interrupt_fd_).
+ bool SetDevicePollInterrupt();
+ bool ClearDevicePollInterrupt();
+
+ //
+ // Device tasks, to be run on device_poll_thread_.
+ //
+
+ // The device task.
+ void DevicePollTask(unsigned int poll_fds);
+
+ //
+ // Safe from any thread.
+ //
+
+ // Error notification (using PostTask() to child thread, if necessary).
+ void NotifyError(Error error);
+
+ // Set the encoder_thread_ state (using PostTask to encoder thread, if
+ // necessary).
+ void SetEncoderState(State state);
+
+ //
+ // Other utility functions. Called on encoder_thread_, unless
+ // encoder_thread_ is not yet started, in which case the child thread can call
+ // these (e.g. in Initialize() or Destroy()).
+ //
+
+ // Create the buffers we need.
+ bool CreateGscInputBuffers();
+ bool CreateGscOutputBuffers();
+ bool SetMfcFormats();
+ bool CreateMfcInputBuffers();
+ bool CreateMfcOutputBuffers();
+
+ // Set encoding parameters.
+ void SetBitrate(int32 bitrate);
+
+ // Destroy these buffers.
+ void DestroyGscInputBuffers();
+ void DestroyGscOutputBuffers();
+ void DestroyMfcInputBuffers();
+ void DestroyMfcOutputBuffers();
+
+ // Our original calling message loop for the child thread.
+ const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
+
+ // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or
+ // device worker threads back to the child thread. Because the worker threads
+ // are members of this class, any task running on those threads is guaranteed
+ // that this object is still alive. As a result, tasks posted from the child
+ // thread to the encoder or device thread should use base::Unretained(this),
+ // and tasks posted the other way should use |weak_this_|.
+ base::WeakPtrFactory<ExynosVideoEncodeAccelerator> weak_this_ptr_factory_;
+ base::WeakPtr<ExynosVideoEncodeAccelerator> weak_this_;
+
+ // To expose client callbacks from VideoEncodeAccelerator.
+ // NOTE: all calls to these objects *MUST* be executed on
+ // child_message_loop_proxy_.
+ base::WeakPtrFactory<Client> client_ptr_factory_;
+ base::WeakPtr<Client> client_;
+
+ //
+ // Encoder state, owned and operated by encoder_thread_.
+ // Before encoder_thread_ has started, the encoder state is managed by
+ // the child (main) thread. After encoder_thread_ has started, the encoder
+ // thread should be the only one managing these.
+ //
+
+ // This thread services tasks posted from the VEA API entry points by the
+ // child thread and device service callbacks posted from the device thread.
+ base::Thread encoder_thread_;
+ // Encoder state machine state.
+ State encoder_state_;
+ // The visible/allocated sizes of the input frame.
+ gfx::Size input_visible_size_;
+ gfx::Size input_allocated_size_;
+ // The visible/allocated sizes of the color-converted frame.
+ gfx::Size converted_visible_size_;
+ gfx::Size converted_allocated_size_;
+ // The visible/allocated sizes of the output frame.
+ gfx::Size output_visible_size_;
+ // The required byte size of output BitstreamBuffers.
+ size_t output_buffer_byte_size_;
+
+ // Cached stream header.
+ scoped_ptr<uint8[]> stream_header_;
+ size_t stream_header_size_;
+
+ // Bitstream buffers ready to be used to return encoded output.
+ std::vector<linked_ptr<BitstreamBufferRef> > encoder_bitstream_buffers_;
+
+ // Buffers ready to be encoded.
+ std::list<int> encoder_input_queue_;
+
+ // Encoded buffers ready to return to the client.
+ std::list<int> encoder_output_queue_;
+
+ // Flag if we are encoding the output (and using MFC).
+ bool do_output_encoding_;
+
+ // Flag if we are encoding from the backbuffer (instead of a CPU allocation).
+ const bool do_encode_from_backbuffer_;
+
+ // GSC color conversion device.
+ int gsc_fd_;
+ // GSC input buffer state.
+ bool gsc_input_streamon_;
+ // GSC input buffers enqueued to device.
+ int gsc_input_buffer_queued_count_;
+ // Mapping of int index to GSC input buffer record.
+ std::vector<GscInputRecord> gsc_input_buffer_map_;
+
+ // GSC output buffer state.
+ bool gsc_output_streamon_;
+ // GSC output buffers enqueued to device.
+ int gsc_output_buffer_queued_count_;
+ // Output buffers ready to use, as a LIFO since we don't care about ordering.
+ std::vector<int> gsc_free_output_buffers_;
+ // Mapping of int index to GSC output buffer record.
+ std::vector<GscOutputRecord> gsc_output_buffer_map_;
+
+ // Completed GSC outputs, waiting for GSC.
+ std::list<int> gsc_output_mfc_input_queue_;
+
+ // MFC video encoding device.
+ int mfc_fd_;
+
+ // MFC input buffer state.
+ bool mfc_input_streamon_;
+ // MFC input buffers enqueued to device.
+ int mfc_input_buffer_queued_count_;
+ // Input buffers ready to use, as a LIFO since we don't care about ordering.
+ std::vector<int> mfc_free_input_buffers_;
+ // Mapping of int index to MFC input buffer record.
+ std::vector<MfcInputRecord> mfc_input_buffer_map_;
+
+ // MFC output buffer state.
+ bool mfc_output_streamon_;
+ // MFC output buffers enqueued to device.
+ int mfc_output_buffer_queued_count_;
+ // Output buffers ready to use, as a LIFO since we don't care about ordering.
+ std::vector<int> mfc_free_output_buffers_;
+ // Mapping of int index to MFC output buffer record.
+ std::vector<MfcOutputRecord> mfc_output_buffer_map_;
+
+ //
+ // The device polling thread handles notifications of V4L2 device changes.
+ //
+
+ // The thread.
+ base::Thread device_poll_thread_;
+ // eventfd fd to signal device poll thread when its poll() should be
+ // interrupted.
+ int device_poll_interrupt_fd_;
+
+ //
+ // Other state, held by child (main) thread.
+ //
+
+ // Make our context current before running any EGL entry points.
+ base::Callback<bool(void)> make_context_current_;
+
+ // Input buffers ready to use, as a LIFO since we don't care about ordering.
+ std::vector<int> gsc_free_input_buffers_;
+
+ // EGL state
+ const EGLDisplay egl_display_;
+
+ // The codec we'll be decoding for.
+ media::VideoCodecProfile video_profile_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_
« no previous file with comments | « content/common/gpu/gl_surface_encoder.cc ('k') | content/common/gpu/media/exynos_video_encode_accelerator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698