mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 09:40:37 +00:00
30f382fcdf
Optimize gst_vaapiencode_handle_frame() to avoid extra memory allocation, and in particular the GstVaapiEncObjUserData object. i.e. directly use the VA surface proxy from the source buffer. This also makes the user data attached to the GstVideoCodecFrame more consistent between both the decoder and encoder plug-in elements.
598 lines
18 KiB
C
598 lines
18 KiB
C
/*
|
|
* gstvaapiencoder_objects.c - VA encoder objects abstraction
|
|
*
|
|
* Copyright (C) 2013 Intel Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "sysdeps.h"
|
|
#include "glibcompat.h"
|
|
|
|
#include "gstvaapiencoder_objects.h"
|
|
#include "gstvaapiencoder.h"
|
|
#include "gstvaapiencoder_priv.h"
|
|
#include "gstvaapisurfaceproxy_priv.h"
|
|
#include "gstvaapiutils.h"
|
|
|
|
#define DEBUG 1
|
|
#include "gstvaapidebug.h"
|
|
|
|
#define GET_ENCODER(obj) GST_VAAPI_ENCODER_CAST((obj)->parent_instance.codec)
|
|
#define GET_VA_DISPLAY(obj) GST_VAAPI_ENCODER_VA_DISPLAY(GET_ENCODER(obj))
|
|
#define GET_VA_CONTEXT(obj) GST_VAAPI_ENCODER_VA_CONTEXT(GET_ENCODER(obj))
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- Encoder Coded Data --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiCodedBuffer, gst_vaapi_coded_buffer);
|
|
|
|
void
|
|
gst_vaapi_coded_buffer_destroy (GstVaapiCodedBuffer * buffer)
|
|
{
|
|
gst_vaapi_coded_buffer_unmap (buffer);
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (buffer), &buffer->buf_id);
|
|
buffer->segment_list = NULL;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_coded_buffer_create (GstVaapiCodedBuffer * codec_buffer,
|
|
const GstVaapiCodecObjectConstructorArgs * args)
|
|
{
|
|
codec_buffer->buf_id = VA_INVALID_ID;
|
|
codec_buffer->segment_list = NULL;
|
|
return vaapi_create_buffer (GET_VA_DISPLAY (codec_buffer),
|
|
GET_VA_CONTEXT (codec_buffer),
|
|
VAEncCodedBufferType,
|
|
args->param_size, args->param, &codec_buffer->buf_id, NULL);
|
|
}
|
|
|
|
GstVaapiCodedBuffer *
|
|
gst_vaapi_coded_buffer_new (GstVaapiEncoder * encoder,
|
|
gconstpointer param, guint param_size)
|
|
{
|
|
GstVaapiCodecObject *object;
|
|
|
|
object = gst_vaapi_codec_object_new (&GstVaapiCodedBufferClass,
|
|
GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
|
|
if (!object)
|
|
return NULL;
|
|
return GST_VAAPI_CODED_BUFFER_CAST (object);
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf, void **data)
|
|
{
|
|
g_return_val_if_fail (buf->buf_id != VA_INVALID_ID, FALSE);
|
|
|
|
if (buf->segment_list)
|
|
goto end;
|
|
buf->segment_list = vaapi_map_buffer (GET_VA_DISPLAY (buf), buf->buf_id);
|
|
if (!buf->segment_list)
|
|
return FALSE;
|
|
end:
|
|
if (data)
|
|
*data = buf->segment_list;
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf)
|
|
{
|
|
if (buf->buf_id != VA_INVALID_ID && buf->segment_list)
|
|
vaapi_unmap_buffer (GET_VA_DISPLAY (buf),
|
|
buf->buf_id, (void **) (&buf->segment_list));
|
|
}
|
|
|
|
gint32
|
|
gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf)
|
|
{
|
|
gint32 size;
|
|
VACodedBufferSegment *segment;
|
|
if (!gst_vaapi_coded_buffer_map (buf, NULL))
|
|
return -1;
|
|
|
|
size = 0;
|
|
segment = buf->segment_list;
|
|
while (segment) {
|
|
size += segment->size;
|
|
segment = (VACodedBufferSegment *) segment->next;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_coded_buffer_get_buffer (GstVaapiCodedBuffer * buf,
|
|
GstBuffer * output)
|
|
{
|
|
gint32 offset;
|
|
VACodedBufferSegment *segment;
|
|
|
|
g_assert (output);
|
|
g_return_val_if_fail (output, FALSE);
|
|
|
|
offset = 0;
|
|
segment = buf->segment_list;
|
|
while (segment) {
|
|
if (gst_buffer_fill (output, offset, segment->buf, segment->size)
|
|
!= segment->size)
|
|
return FALSE;
|
|
offset += segment->size;
|
|
segment = (VACodedBufferSegment *) segment->next;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- Encoder Packed Header --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncPackedHeader,
|
|
gst_vaapi_enc_packed_header);
|
|
|
|
void
|
|
gst_vaapi_enc_packed_header_destroy (GstVaapiEncPackedHeader * packed_header)
|
|
{
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (packed_header),
|
|
&packed_header->param_id);
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (packed_header),
|
|
&packed_header->data_id);
|
|
packed_header->param = NULL;
|
|
packed_header->data = NULL;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_packed_header_create (GstVaapiEncPackedHeader * packed_header,
|
|
const GstVaapiCodecObjectConstructorArgs * args)
|
|
{
|
|
gboolean success;
|
|
|
|
packed_header->param_id = VA_INVALID_ID;
|
|
packed_header->param = NULL;
|
|
packed_header->data_id = VA_INVALID_ID;
|
|
packed_header->data = NULL;
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (packed_header),
|
|
GET_VA_CONTEXT (packed_header),
|
|
VAEncPackedHeaderParameterBufferType,
|
|
args->param_size,
|
|
args->param, &packed_header->param_id, &packed_header->param);
|
|
if (!success)
|
|
return FALSE;
|
|
|
|
if (!args->data_size)
|
|
return TRUE;
|
|
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (packed_header),
|
|
GET_VA_CONTEXT (packed_header),
|
|
VAEncPackedHeaderDataBufferType,
|
|
args->data_size,
|
|
args->data, &packed_header->data_id, &packed_header->data);
|
|
if (!success)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GstVaapiEncPackedHeader *
|
|
gst_vaapi_enc_packed_header_new (GstVaapiEncoder * encoder,
|
|
gconstpointer param, guint param_size, gconstpointer data, guint data_size)
|
|
{
|
|
GstVaapiCodecObject *object;
|
|
|
|
object = gst_vaapi_codec_object_new (&GstVaapiEncPackedHeaderClass,
|
|
GST_VAAPI_CODEC_BASE (encoder), param, param_size, data, data_size, 0);
|
|
return GST_VAAPI_ENC_PACKED_HEADER (object);
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_packed_header_set_data (GstVaapiEncPackedHeader * packed_header,
|
|
gconstpointer data, guint data_size)
|
|
{
|
|
gboolean success;
|
|
|
|
g_assert (packed_header->data_id == VA_INVALID_ID);
|
|
if (packed_header->data_id != VA_INVALID_ID) {
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (packed_header),
|
|
&packed_header->data_id);
|
|
packed_header->data = NULL;
|
|
}
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (packed_header),
|
|
GET_VA_CONTEXT (packed_header),
|
|
VAEncPackedHeaderDataBufferType,
|
|
data_size, data, &packed_header->data_id, &packed_header->data);
|
|
if (!success)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- Encoder Sequence --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncSequence, gst_vaapi_enc_sequence);
|
|
|
|
void
|
|
gst_vaapi_enc_sequence_destroy (GstVaapiEncSequence * sequence)
|
|
{
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (sequence), &sequence->param_id);
|
|
sequence->param = NULL;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_sequence_create (GstVaapiEncSequence * sequence,
|
|
const GstVaapiCodecObjectConstructorArgs * args)
|
|
{
|
|
gboolean success;
|
|
|
|
sequence->param_id = VA_INVALID_ID;
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (sequence),
|
|
GET_VA_CONTEXT (sequence),
|
|
VAEncSequenceParameterBufferType,
|
|
args->param_size, args->param, &sequence->param_id, &sequence->param);
|
|
if (!success)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GstVaapiEncSequence *
|
|
gst_vaapi_enc_sequence_new (GstVaapiEncoder * encoder,
|
|
gconstpointer param, guint param_size)
|
|
{
|
|
GstVaapiCodecObject *object;
|
|
|
|
object = gst_vaapi_codec_object_new (&GstVaapiEncSequenceClass,
|
|
GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
|
|
return GST_VAAPI_ENC_SEQUENCE_CAST (object);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- Encoder Slice --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncSlice, gst_vaapi_enc_slice);
|
|
|
|
void
|
|
gst_vaapi_enc_slice_destroy (GstVaapiEncSlice * slice)
|
|
{
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (slice), &slice->param_id);
|
|
slice->param = NULL;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_slice_create (GstVaapiEncSlice * slice,
|
|
const GstVaapiCodecObjectConstructorArgs * args)
|
|
{
|
|
gboolean success;
|
|
|
|
slice->param_id = VA_INVALID_ID;
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (slice),
|
|
GET_VA_CONTEXT (slice),
|
|
VAEncSliceParameterBufferType,
|
|
args->param_size, args->param, &slice->param_id, &slice->param);
|
|
if (!success)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GstVaapiEncSlice *
|
|
gst_vaapi_enc_slice_new (GstVaapiEncoder * encoder,
|
|
gconstpointer param, guint param_size)
|
|
{
|
|
GstVaapiCodecObject *object;
|
|
|
|
object = gst_vaapi_codec_object_new (&GstVaapiEncSliceClass,
|
|
GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
|
|
return GST_VAAPI_ENC_SLICE_CAST (object);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- Encoder Misc Parameter Buffer --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncMiscParam, gst_vaapi_enc_misc_param);
|
|
|
|
void
|
|
gst_vaapi_enc_misc_param_destroy (GstVaapiEncMiscParam * misc)
|
|
{
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (misc), &misc->param_id);
|
|
misc->param = NULL;
|
|
misc->impl = NULL;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_misc_param_create (GstVaapiEncMiscParam * misc,
|
|
const GstVaapiCodecObjectConstructorArgs * args)
|
|
{
|
|
gboolean success;
|
|
|
|
misc->param_id = VA_INVALID_ID;
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (misc),
|
|
GET_VA_CONTEXT (misc),
|
|
VAEncMiscParameterBufferType,
|
|
args->param_size, args->param, &misc->param_id, &misc->param);
|
|
if (!success)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GstVaapiEncMiscParam *
|
|
gst_vaapi_enc_misc_param_new (GstVaapiEncoder * encoder,
|
|
VAEncMiscParameterType type, guint total_size)
|
|
{
|
|
GstVaapiCodecObject *object;
|
|
GstVaapiEncMiscParam *misc_obj;
|
|
VAEncMiscParameterBuffer *misc;
|
|
|
|
object = gst_vaapi_codec_object_new (&GstVaapiEncMiscParamClass,
|
|
GST_VAAPI_CODEC_BASE (encoder), NULL, total_size, NULL, 0, 0);
|
|
if (!object)
|
|
return NULL;
|
|
|
|
misc_obj = GST_VAAPI_ENC_MISC_PARAM_CAST (object);
|
|
misc = misc_obj->param;
|
|
misc->type = type;
|
|
misc_obj->impl = misc->data;
|
|
g_assert (misc_obj->impl);
|
|
return misc_obj;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- Encoder Picture --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncPicture, gst_vaapi_enc_picture);
|
|
|
|
static void
|
|
destroy_vaapi_obj_cb (gpointer data, gpointer user_data)
|
|
{
|
|
GstVaapiMiniObject *const object = data;
|
|
|
|
gst_vaapi_mini_object_unref (object);
|
|
}
|
|
|
|
void
|
|
gst_vaapi_enc_picture_destroy (GstVaapiEncPicture * picture)
|
|
{
|
|
if (picture->packed_headers) {
|
|
g_ptr_array_foreach (picture->packed_headers, destroy_vaapi_obj_cb, NULL);
|
|
g_ptr_array_free (picture->packed_headers, TRUE);
|
|
picture->packed_headers = NULL;
|
|
}
|
|
if (picture->misc_buffers) {
|
|
g_ptr_array_foreach (picture->misc_buffers, destroy_vaapi_obj_cb, NULL);
|
|
g_ptr_array_free (picture->misc_buffers, TRUE);
|
|
picture->misc_buffers = NULL;
|
|
}
|
|
if (picture->slices) {
|
|
g_ptr_array_foreach (picture->slices, destroy_vaapi_obj_cb, NULL);
|
|
g_ptr_array_free (picture->slices, TRUE);
|
|
picture->slices = NULL;
|
|
}
|
|
gst_vaapi_mini_object_replace (
|
|
(GstVaapiMiniObject **) (&picture->sequence), NULL);
|
|
|
|
gst_vaapi_surface_proxy_replace (&picture->proxy, NULL);
|
|
picture->surface_id = VA_INVALID_ID;
|
|
picture->surface = NULL;
|
|
|
|
vaapi_destroy_buffer (GET_VA_DISPLAY (picture), &picture->param_id);
|
|
picture->param = NULL;
|
|
picture->param = NULL;
|
|
|
|
if (picture->frame) {
|
|
gst_video_codec_frame_unref (picture->frame);
|
|
picture->frame = NULL;
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture,
|
|
const GstVaapiCodecObjectConstructorArgs * args)
|
|
{
|
|
GstVideoCodecFrame *const frame = (GstVideoCodecFrame *)args->data;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (frame != NULL, FALSE);
|
|
|
|
picture->proxy = gst_video_codec_frame_get_user_data (frame);
|
|
if (!gst_vaapi_surface_proxy_ref (picture->proxy))
|
|
return FALSE;
|
|
|
|
picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE (picture->proxy);
|
|
if (!picture->surface)
|
|
return FALSE;
|
|
|
|
picture->surface_id = GST_VAAPI_OBJECT_ID (picture->surface);
|
|
if (picture->surface_id == VA_INVALID_ID)
|
|
return FALSE;
|
|
|
|
picture->sequence = NULL;
|
|
picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
|
|
picture->pts = GST_CLOCK_TIME_NONE;
|
|
picture->frame_num = 0;
|
|
picture->poc = 0;
|
|
|
|
picture->param_id = VA_INVALID_ID;
|
|
picture->param_size = args->param_size;
|
|
picture->param = NULL;
|
|
success = vaapi_create_buffer (GET_VA_DISPLAY (picture),
|
|
GET_VA_CONTEXT (picture),
|
|
VAEncPictureParameterBufferType,
|
|
args->param_size, args->param, &picture->param_id, &picture->param);
|
|
if (!success)
|
|
return FALSE;
|
|
picture->param_size = args->param_size;
|
|
|
|
picture->packed_headers = g_ptr_array_new ();
|
|
picture->misc_buffers = g_ptr_array_new ();
|
|
picture->slices = g_ptr_array_new ();
|
|
|
|
g_assert (picture->packed_headers && picture->misc_buffers
|
|
&& picture->slices);
|
|
if (!picture->packed_headers || !picture->misc_buffers || !picture->slices)
|
|
return FALSE;
|
|
|
|
picture->frame = gst_video_codec_frame_ref (frame);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GstVaapiEncPicture *
|
|
gst_vaapi_enc_picture_new (GstVaapiEncoder * encoder,
|
|
gconstpointer param, guint param_size, GstVideoCodecFrame * frame)
|
|
{
|
|
GstVaapiCodecObject *object;
|
|
|
|
object = gst_vaapi_codec_object_new (&GstVaapiEncPictureClass,
|
|
GST_VAAPI_CODEC_BASE (encoder), param, param_size, frame, 0, 0);
|
|
if (!object)
|
|
return NULL;
|
|
return GST_VAAPI_ENC_PICTURE_CAST (object);
|
|
}
|
|
|
|
void
|
|
gst_vaapi_enc_picture_set_sequence (GstVaapiEncPicture * picture,
|
|
GstVaapiEncSequence * sequence)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_PICTURE (picture));
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_SEQUENCE (sequence));
|
|
|
|
g_assert (sequence);
|
|
gst_vaapi_mini_object_replace (
|
|
(GstVaapiMiniObject **) (&picture->sequence),
|
|
GST_VAAPI_MINI_OBJECT (sequence));
|
|
}
|
|
|
|
void
|
|
gst_vaapi_enc_picture_add_packed_header (GstVaapiEncPicture * picture,
|
|
GstVaapiEncPackedHeader * header)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_PICTURE (picture));
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_PACKED_HEADER (header));
|
|
|
|
g_assert (picture->packed_headers);
|
|
g_ptr_array_add (picture->packed_headers,
|
|
gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (header)));
|
|
}
|
|
|
|
void
|
|
gst_vaapi_enc_picture_add_misc_buffer (GstVaapiEncPicture * picture,
|
|
GstVaapiEncMiscParam * misc)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_PICTURE (picture));
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_MISC_PARAM (misc));
|
|
|
|
g_assert (picture->misc_buffers);
|
|
g_ptr_array_add (picture->misc_buffers,
|
|
gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (misc)));
|
|
}
|
|
|
|
void
|
|
gst_vaapi_enc_picture_add_slice (GstVaapiEncPicture * picture,
|
|
GstVaapiEncSlice * slice)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_PICTURE (picture));
|
|
g_return_if_fail (GST_VAAPI_IS_ENC_SLICE (slice));
|
|
|
|
g_ptr_array_add (picture->slices,
|
|
gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (slice)));
|
|
}
|
|
|
|
static gboolean
|
|
do_encode (VADisplay dpy, VAContextID ctx, VABufferID * buf_id, void **buf_ptr)
|
|
{
|
|
VAStatus status;
|
|
|
|
vaapi_unmap_buffer (dpy, *buf_id, buf_ptr);
|
|
|
|
status = vaRenderPicture (dpy, ctx, buf_id, 1);
|
|
if (!vaapi_check_status (status, "vaRenderPicture()"))
|
|
return FALSE;
|
|
|
|
/* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
|
|
vaapi_destroy_buffer (dpy, buf_id);
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gst_vaapi_enc_picture_encode (GstVaapiEncPicture * picture)
|
|
{
|
|
GstVaapiEncSequence *sequence;
|
|
GstVaapiEncPackedHeader *packed_header;
|
|
GstVaapiEncMiscParam *misc;
|
|
GstVaapiEncSlice *slice;
|
|
VADisplay va_display;
|
|
VAContextID va_context;
|
|
VAStatus status;
|
|
guint i;
|
|
|
|
g_return_val_if_fail (GST_VAAPI_IS_ENC_PICTURE (picture), FALSE);
|
|
g_return_val_if_fail (picture->surface_id != VA_INVALID_SURFACE, FALSE);
|
|
|
|
va_display = GET_VA_DISPLAY (picture);
|
|
va_context = GET_VA_CONTEXT (picture);
|
|
|
|
GST_DEBUG ("encode picture 0x%08x", picture->surface_id);
|
|
|
|
status = vaBeginPicture (va_display, va_context, picture->surface_id);
|
|
if (!vaapi_check_status (status, "vaBeginPicture()"))
|
|
return FALSE;
|
|
|
|
/* encode sequence parameter */
|
|
sequence = picture->sequence;
|
|
if (sequence) {
|
|
if (!do_encode (va_display, va_context,
|
|
&sequence->param_id, &sequence->param))
|
|
return FALSE;
|
|
}
|
|
|
|
/* encode picture parameter */
|
|
if (!do_encode (va_display, va_context, &picture->param_id, &picture->param))
|
|
return FALSE;
|
|
|
|
/* encode packed headers */
|
|
for (i = 0; i < picture->packed_headers->len; i++) {
|
|
packed_header = g_ptr_array_index (picture->packed_headers, i);
|
|
if (!do_encode (va_display, va_context,
|
|
&packed_header->param_id, &packed_header->param) ||
|
|
!do_encode (va_display, va_context,
|
|
&packed_header->data_id, &packed_header->data))
|
|
return FALSE;
|
|
}
|
|
|
|
/* encode misc buffers */
|
|
for (i = 0; i < picture->misc_buffers->len; i++) {
|
|
misc = g_ptr_array_index (picture->misc_buffers, i);
|
|
if (!do_encode (va_display, va_context, &misc->param_id, &misc->param))
|
|
return FALSE;
|
|
}
|
|
|
|
/* encode slice parameters */
|
|
for (i = 0; i < picture->slices->len; i++) {
|
|
slice = g_ptr_array_index (picture->slices, i);
|
|
if (!do_encode (va_display, va_context, &slice->param_id, &slice->param))
|
|
return FALSE;
|
|
}
|
|
|
|
status = vaEndPicture (va_display, va_context);
|
|
if (!vaapi_check_status (status, "vaEndPicture()"))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|