Index: content/common/gpu/media/vaapi_h264_decoder.h |
diff --git a/content/common/gpu/media/vaapi_h264_decoder.h b/content/common/gpu/media/vaapi_h264_decoder.h |
index 8abb28baf9eb418668c2ec329bcee84869d89e2a..5b2df60d3ce0177da544e07efb4ccac598254c3a 100644 |
--- a/content/common/gpu/media/vaapi_h264_decoder.h |
+++ b/content/common/gpu/media/vaapi_h264_decoder.h |
@@ -9,55 +9,52 @@ |
#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_ |
#define CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_ |
-#include <GL/glx.h> |
- |
-#include <queue> |
+#include <vector> |
#include "base/callback_forward.h" |
-#include "base/lazy_instance.h" |
#include "base/memory/linked_ptr.h" |
+#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
#include "content/common/gpu/media/h264_dpb.h" |
#include "content/common/gpu/media/h264_parser.h" |
-#include "media/base/video_decoder_config.h" |
+#include "content/common/gpu/media/vaapi_wrapper.h" |
#include "media/base/limits.h" |
-#include "third_party/libva/va/va.h" |
namespace content { |
-// An H264 decoder for use for VA-API-specific decoding. Provides features not |
-// supported by libva, including stream parsing, reference picture management |
-// and other operations not supported by the HW codec. |
+// An H264 decoder that utilizes VA-API. Provides features not supported by |
+// the VA-API userspace library (libva), including stream parsing, reference |
+// picture management and other operations not supported by the HW codec. |
// |
// Provides functionality to allow plugging VAAPI HW acceleration into the |
// VDA framework. |
// |
// Clients of this class are expected to pass H264 Annex-B byte stream and |
-// will receive decoded pictures via client-provided |OutputPicCB|. |
+// will receive decoded surfaces via client-provided |OutputPicCB|. |
// |
-// If used in multi-threaded environment, some of the functions have to be |
-// called on the child thread, i.e. the main thread of the GPU process |
-// (the one that has the GLX context passed to Initialize() set as current). |
-// This is essential so that the GLX calls can work properly. |
-// Decoder thread, on the other hand, does not require a GLX context and should |
-// be the same as the one on which Decode*() functions are called. |
+// This class must be created, called and destroyed on a single thread, and |
+// does nothing internally on any other thread. |
class VaapiH264Decoder { |
public: |
- // Callback invoked on the client when a picture is to be displayed. |
- // Arguments: input buffer id, output buffer id (both provided by the client |
- // at the time of Decode() and AssignPictureBuffer() calls). |
- typedef base::Callback<void(int32, int32)> OutputPicCB; |
- |
- // Callback invoked on the client to start a GPU job to decode and render |
- // a video frame into a pixmap/texture. Callee has to call SubmitDecode() |
- // for the given picture. |
- // Arguments: output buffer id (provided by the client at the time of |
- // AssignPictureBuffer() call), va buffer and slice buffer queues to be |
- // passed to SubmitDecode(). |
+ // Callback invoked on the client when a surface is to be displayed. |
+ // Arguments: input buffer id provided at the time of Decode() |
+ // and VASurface to output. |
typedef base::Callback< |
- void(int32, |
- scoped_ptr<std::queue<VABufferID> >, |
- scoped_ptr<std::queue<VABufferID> >)> SubmitDecodeCB; |
+ void(int32, const scoped_refptr<VASurface>&)> OutputPicCB; |
+ |
+ enum VAVDAH264DecoderFailure { |
+ FRAME_MBS_ONLY_FLAG_NOT_ONE = 0, |
+ GAPS_IN_FRAME_NUM = 1, |
+ MID_STREAM_RESOLUTION_CHANGE = 2, |
+ INTERLACED_STREAM = 3, |
+ VAAPI_ERROR = 4, |
+ VAVDA_H264_DECODER_FAILURES_MAX, |
+ }; |
+ |
+ // Callback to report errors for UMA purposes, not used to return errors |
+ // to clients. |
+ typedef base::Callback<void(VAVDAH264DecoderFailure error)> |
+ ReportErrorToUmaCB; |
// Decode result codes. |
enum DecResult { |
@@ -67,88 +64,52 @@ class VaapiH264Decoder { |
// to software decoding instead. |
// kStreamError, // Error in stream. |
kReadyToDecode, // Successfully initialized. |
- kDecodedFrame, // Successfully decoded a frame. |
kNeedMoreStreamData, // Need more stream data to decode the next frame. |
kNoOutputAvailable, // Waiting for the client to free up output surfaces. |
}; |
- VaapiH264Decoder(); |
- // Should be called on the GLX thread, for the surface cleanup to work |
- // properly. |
- ~VaapiH264Decoder(); |
+ // |vaapi_wrapper| should be initialized. |
+ // |output_pic_cb| notifies the client a surface is to be displayed. |
+ // |report_error_to_uma_cb| called on errors for UMA purposes, not used |
+ // to report errors to clients. |
+ VaapiH264Decoder(VaapiWrapper* vaapi_wrapper, |
+ const OutputPicCB& output_pic_cb, |
+ const ReportErrorToUmaCB& report_error_to_uma_cb); |
- // Initializes and sets up libva connection and GL/X11 resources. |
- // Must be called on the GLX thread with |glx_context| being current and |
- // with decoder thread not yet running. |
- // |output_pic_cb| will be called to notify when a picture can be displayed. |
- bool Initialize(media::VideoCodecProfile profile, |
- Display* x_display, |
- GLXContext glx_context, |
- const base::Callback<bool(void)>& make_context_current, |
- const OutputPicCB& output_pic_cb, |
- const SubmitDecodeCB& submit_decode_cb) WARN_UNUSED_RESULT; |
- void Destroy(); |
- |
- // Notify the decoder that this output buffer has been consumed and |
- // can be reused (overwritten). |
- // Must be run on the decoder thread. |
- void ReusePictureBuffer(int32 picture_buffer_id); |
- |
- // Give a new picture buffer (texture) to decoder for use. |
- // Must be run on the GLX thread with decoder thread not yet running. |
- bool AssignPictureBuffer(int32 picture_buffer_id, uint32 texture_id) |
- WARN_UNUSED_RESULT; |
- |
- // Decode and put results into texture associated with given |
- // |picture_buffer_id|, using the buffers provided as arguments. Takes |
- // ownership of queues' memory and frees it once done. |
- // Must be run on the GLX thread. |
- bool SubmitDecode( |
- int32 picture_buffer_id, |
- scoped_ptr<std::queue<VABufferID> > va_bufs, |
- scoped_ptr<std::queue<VABufferID> > slice_bufs) WARN_UNUSED_RESULT; |
+ ~VaapiH264Decoder(); |
// Have the decoder flush its state and trigger output of all previously |
- // decoded pictures via OutputPicCB. |
- // Returns false if any of the resulting invocations of the callback fail. |
+ // decoded surfaces via OutputPicCB. Return false on failure. |
bool Flush() WARN_UNUSED_RESULT; |
- // Called while decoding. |
- // Stop decoding, discarding all remaining input/output, but do not flush |
- // state, so the playback of the same stream can be resumed (possibly from |
- // another location). |
+ // To be called during decoding. |
+ // Stop (pause) decoding, discarding all remaining inputs and outputs, |
+ // but do not flush decoder state, so that the playback can be resumed later, |
+ // possibly from a different location. |
void Reset(); |
// Set current stream data pointer to |ptr| and |size|. |
- // Must be run on decoder thread. |
void SetStream(uint8* ptr, size_t size); |
- // Start parsing stream to detect picture sizes. Does not produce any |
- // decoded pictures and can be called without providing output textures. |
- // Also to be used after Reset() to find a suitable location in the |
- // stream to resume playback from. |
+ // To be called at the start of decode or after reset. |
+ // When this call returns kReadyToDecode, the decoder is in a suitable |
+ // location in the stream to begin/resume decoding from and subsequent |
+ // decode requests should go via DecodeOneFrame. |
DecResult DecodeInitial(int32 input_id) WARN_UNUSED_RESULT; |
// Runs until a frame is decoded or end of provided stream data buffer |
- // is reached. Decoded pictures will be returned asynchronously via |
- // OutputPicCB. |
+ // is reached. Decoded surfaces will be returned asynchronously via |
+ // OutputPicCB. Should be called after DecodeInitial returns kReadyToDecode. |
DecResult DecodeOneFrame(int32 input_id) WARN_UNUSED_RESULT; |
- // Return dimensions for output buffer (texture) allocation. |
+ // Return dimensions/required number of output surfaces that client should |
+ // be ready to provide for the decoder to function properly. |
// Valid only after a successful DecodeInitial(). |
- int pic_height() { return pic_height_; } |
- int pic_width() { return pic_width_; } |
- |
- // Return the number of output pictures required for decoding. |
- // Valid after a successful DecodeInitial(). |
+ gfx::Size GetPicSize() { return pic_size_; } |
size_t GetRequiredNumOfPictures(); |
- // Do any necessary initialization before the sandbox is enabled. |
- static void PreSandboxInitialization(); |
- |
- // Lazily initialize static data after sandbox is enabled. Return false on |
- // init failure. |
- static bool PostSandboxInitialization(); |
+ // To be used by the client to feed decoder with output surfaces. |
+ void ReuseSurface(const scoped_refptr<VASurface>& va_surface); |
private: |
// We need to keep at most kDPBMaxSize pictures in DPB for |
@@ -164,17 +125,11 @@ class VaapiH264Decoder { |
// Internal state of the decoder. |
enum State { |
- kUninitialized, // Initialize() not yet called. |
- kInitialized, // Initialize() called, pictures requested. |
- kDecoding, // DecodeInitial() successful, output surfaces allocated. |
- kAfterReset, // After Reset() during decoding. |
- kError, // Error in kDecoding state. |
+ kIdle, // After initialization or after Reset(), need a resume point. |
+ kDecoding, // DecodeInitial() successful, ready to decode. |
+ kError, // Error in decode, can't continue. |
}; |
- // Get usable framebuffer configuration for use in binding textures |
- // or return false on failure. |
- bool InitializeFBConfig(); |
- |
// Process H264 stream structures. |
bool ProcessSPS(int sps_id); |
bool ProcessPPS(int pps_id); |
@@ -224,20 +179,10 @@ class VaapiH264Decoder { |
// This will also output a picture if one is ready for output. |
bool FinishPicture(); |
- // Convert VideoCodecProfile to VAProfile and set it as active. |
- bool SetProfile(media::VideoCodecProfile profile); |
- |
- // Vaapi-related functions. |
- |
- // Allocates VASurfaces and creates a VAContext for them. |
- bool CreateVASurfaces(); |
- |
- // Destroys allocated VASurfaces and related VAContext. |
- void DestroyVASurfaces(); |
- // Destroys all buffers in |pending_slice_bufs_| and |pending_va_bufs_|. |
- void DestroyPendingBuffers(); |
- // Destroys a list of buffers. |
- void DestroyBuffers(size_t num_va_buffers, const VABufferID* va_buffers); |
+ // Clear DPB contents and remove all surfaces in DPB from *in_use_ list. |
+ // Cleared pictures will be made available for decode, unless they are |
+ // at client waiting to be displayed. |
+ void ClearDPB(); |
// These queue up data for HW decoder to be committed on running HW decode. |
bool SendPPS(); |
@@ -256,11 +201,26 @@ class VaapiH264Decoder { |
// Notifies client that a picture is ready for output. |
bool OutputPic(H264Picture* pic); |
- State state_; |
+ // Output all pictures in DPB that have not been outputted yet. |
+ bool OutputAllRemainingPics(); |
+ |
+ // Represents a frame being decoded. Will always have a VASurface |
+ // assigned to it, which will eventually contain decoded picture data. |
+ class DecodeSurface; |
- // A frame has been sent to hardware as the result of the last |
- // DecodeOneFrame() call. |
- bool frame_ready_at_hw_; |
+ // Assign an available surface to the given PicOrderCnt |poc|, |
+ // removing it from the available surfaces pool. Return true if a surface |
+ // has been found, false otherwise. |
+ bool AssignSurfaceToPoC(int32 input_id, int poc); |
+ |
+ // Indicate that a surface is no longer needed by decoder. |
+ void UnassignSurfaceFromPoC(int poc); |
+ |
+ // Return DecodeSurface assigned to |poc|. |
+ DecodeSurface* DecodeSurfaceByPoC(int poc); |
+ |
+ // Decoder state. |
+ State state_; |
// Parser in use. |
H264Parser parser_; |
@@ -299,65 +259,27 @@ class VaapiH264Decoder { |
int curr_pps_id_; |
// Output picture size. |
- int pic_width_; |
- int pic_height_; |
- |
- // Data queued up for HW decoder, to be committed on next HW decode. |
- std::queue<VABufferID> pending_slice_bufs_; |
- std::queue<VABufferID> pending_va_bufs_; |
- |
- // Manages binding of a client-provided output buffer (texture) to VASurface. |
- class DecodeSurface; |
- |
- // Maps output_buffer_id to a decode surface. Used to look up surfaces |
- // on requests from the client. |
- typedef std::map<int32, linked_ptr<DecodeSurface> > DecodeSurfaces; |
- DecodeSurfaces decode_surfaces_; |
+ gfx::Size pic_size_; |
- // Number of decode surface currently available for decoding. |
- int num_available_decode_surfaces_; |
+ // Maps H.264 PicOrderCount to currently used DecodeSurfaces; |
+ typedef std::map<int, linked_ptr<DecodeSurface> > DecSurfacesInUse; |
+ DecSurfacesInUse decode_surfaces_in_use_; |
- // Maps decode surfaces to PicOrderCount, used to look up output buffers |
- // when a decision to output a picture has been made. |
- typedef std::map<int, DecodeSurface*> POCToDecodeSurfaces; |
- POCToDecodeSurfaces poc_to_decode_surfaces_; |
- |
- // Find an available surface and assign it to given PicOrderCnt |poc|, |
- // removing it from the available surfaces pool. Return true if a surface |
- // has been found, false otherwise. |
- bool AssignSurfaceToPoC(int poc); |
- |
- // Mark a surface as unused for decoding, unassigning it from |poc|. If the |
- // corresponding picture is not at client to be displayed, |
- // release the surface. |
- void UnassignSurfaceFromPoC(int poc); |
+ // Unused VA surfaces returned by client, ready to be reused. |
+ std::vector<scoped_refptr<VASurface> > available_va_surfaces_; |
// The id of current input buffer, which will be associated with an |
- // output picture if a frame is decoded successfully. |
+ // output surface when a frame is successfully decoded. |
int32 curr_input_id_; |
- // Any method that uses GL/VA routines probably wants to make sure |
- // make_context_current_.Run() is called at the top of the method. |
- // X/GLX handles. |
- Display* x_display_; |
- base::Callback<bool(void)> make_context_current_; |
- GLXFBConfig fb_config_; |
- |
- // VA handles. |
- VADisplay va_display_; |
- VAConfigID va_config_id_; |
- VAContextID va_context_id_; |
- VAProfile profile_; |
- bool va_context_created_; |
+ VaapiWrapper* vaapi_wrapper_; |
- // Allocated VASurfaces. |
- VASurfaceID va_surface_ids_[kMaxNumReqPictures]; |
- |
- // Called by decoder when a picture should be outputted. |
+ // Called by decoder when a surface should be outputted. |
OutputPicCB output_pic_cb_; |
- // Called by decoder to post a decode job on the ChildThread. |
- SubmitDecodeCB submit_decode_cb_; |
+ // Called to report decoding error to UMA, not used to indicate errors |
+ // to clients. |
+ ReportErrorToUmaCB report_error_to_uma_cb_; |
// PicOrderCount of the previously outputted frame. |
int last_output_poc_; |
@@ -365,9 +287,6 @@ class VaapiH264Decoder { |
// Maximum size of DPB required by codec level. |
int max_dpb_size_; |
- // Has static initialization of pre-sandbox components completed successfully? |
- static bool pre_sandbox_init_done_; |
- |
DISALLOW_COPY_AND_ASSIGN(VaapiH264Decoder); |
}; |