mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 03:19:40 +00:00
acf106e1a7
This is patch pretends to decouple the assignation of the values in the parameter structures and the VA buffer's parameters setting. It may lead to some issues since HRD, framerate or controlrate may not be handled by the specific encoder, but they are set in the VA buffer's parameters. I leave as it because this patch is just a transitional patch. https://bugzilla.gnome.org/show_bug.cgi?id=783449
635 lines
19 KiB
C
635 lines
19 KiB
C
/*
|
|
* gstvaapiencoder_vp8.c - VP8 encoder
|
|
*
|
|
* Copyright (C) 2015 Intel Corporation
|
|
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
|
|
*
|
|
* 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 <va/va.h>
|
|
#include <va/va_enc_vp8.h>
|
|
#include <gst/base/gstbitwriter.h>
|
|
#include <gst/codecparsers/gstvp8parser.h>
|
|
#include "gstvaapicompat.h"
|
|
#include "gstvaapiencoder_priv.h"
|
|
#include "gstvaapiencoder_vp8.h"
|
|
#include "gstvaapicodedbufferproxy_priv.h"
|
|
#include "gstvaapisurface.h"
|
|
|
|
#define DEBUG 1
|
|
#include "gstvaapidebug.h"
|
|
|
|
/* Define default rate control mode ("constant-qp") */
|
|
#define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
|
|
|
|
/* Supported set of VA rate controls, within this implementation */
|
|
#define SUPPORTED_RATECONTROLS \
|
|
(GST_VAAPI_RATECONTROL_MASK (CQP) | \
|
|
GST_VAAPI_RATECONTROL_MASK (CBR))
|
|
|
|
/* Supported set of tuning options, within this implementation */
|
|
#define SUPPORTED_TUNE_OPTIONS \
|
|
(GST_VAAPI_ENCODER_TUNE_MASK (NONE))
|
|
|
|
/* Supported set of VA packed headers, within this implementation */
|
|
#define SUPPORTED_PACKED_HEADERS \
|
|
(VA_ENC_PACKED_HEADER_NONE)
|
|
|
|
#define DEFAULT_LOOP_FILTER_LEVEL 0
|
|
#define DEFAULT_SHARPNESS_LEVEL 0
|
|
#define DEFAULT_YAC_QI 40
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* --- VP8 Encoder --- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
#define GST_VAAPI_ENCODER_VP8_CAST(encoder) \
|
|
((GstVaapiEncoderVP8 *)(encoder))
|
|
|
|
struct _GstVaapiEncoderVP8
|
|
{
|
|
GstVaapiEncoder parent_instance;
|
|
GstVaapiProfile profile;
|
|
guint loop_filter_level;
|
|
guint sharpness_level;
|
|
guint yac_qi;
|
|
guint frame_num;
|
|
/* reference list */
|
|
GstVaapiSurfaceProxy *last_ref;
|
|
GstVaapiSurfaceProxy *golden_ref;
|
|
GstVaapiSurfaceProxy *alt_ref;
|
|
};
|
|
|
|
/* Derives the profile that suits best to the configuration */
|
|
static GstVaapiEncoderStatus
|
|
ensure_profile (GstVaapiEncoderVP8 * encoder)
|
|
{
|
|
/* Always start from "simple" profile for maximum compatibility */
|
|
encoder->profile = GST_VAAPI_PROFILE_VP8;
|
|
|
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
}
|
|
|
|
/* Derives the profile supported by the underlying hardware */
|
|
static gboolean
|
|
ensure_hw_profile (GstVaapiEncoderVP8 * encoder)
|
|
{
|
|
GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
|
|
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
|
|
GstVaapiProfile profile, profiles[2];
|
|
guint i, num_profiles = 0;
|
|
|
|
profiles[num_profiles++] = encoder->profile;
|
|
|
|
profile = GST_VAAPI_PROFILE_UNKNOWN;
|
|
for (i = 0; i < num_profiles; i++) {
|
|
if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
|
|
profile = profiles[i];
|
|
break;
|
|
}
|
|
}
|
|
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
|
|
goto error_unsupported_profile;
|
|
|
|
GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
error_unsupported_profile:
|
|
{
|
|
GST_ERROR ("unsupported HW profile (0x%08x)", encoder->profile);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
ensure_bitrate (GstVaapiEncoderVP8 * encoder)
|
|
{
|
|
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
|
|
|
|
/* Default compression: 64 bits per macroblock */
|
|
switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
|
|
case GST_VAAPI_RATECONTROL_CBR:
|
|
if (!base_encoder->bitrate) {
|
|
base_encoder->bitrate =
|
|
gst_util_uint64_scale (GST_VAAPI_ENCODER_WIDTH (encoder) *
|
|
GST_VAAPI_ENCODER_HEIGHT (encoder),
|
|
GST_VAAPI_ENCODER_FPS_N (encoder),
|
|
GST_VAAPI_ENCODER_FPS_D (encoder)) / (4 * 1000);
|
|
}
|
|
break;
|
|
default:
|
|
base_encoder->bitrate = 0;
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GstVaapiEncoderStatus
|
|
set_context_info (GstVaapiEncoder * base_encoder)
|
|
{
|
|
GstVaapiEncoderVP8 *encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
|
|
|
|
/* Maximum sizes for common headers (in bytes) */
|
|
enum
|
|
{
|
|
MAX_FRAME_TAG_SIZE = 10,
|
|
MAX_UPDATE_SEGMENTATION_SIZE = 13,
|
|
MAX_MB_LF_ADJUSTMENTS_SIZE = 9,
|
|
MAX_QUANT_INDICES_SIZE = 5,
|
|
MAX_TOKEN_PROB_UPDATE_SIZE = 1188,
|
|
MAX_MV_PROBE_UPDATE_SIZE = 38,
|
|
MAX_REST_OF_FRAME_HDR_SIZE = 15
|
|
};
|
|
|
|
if (!ensure_hw_profile (encoder))
|
|
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
|
|
|
base_encoder->num_ref_frames = 3;
|
|
|
|
/* Only YUV 4:2:0 formats are supported for now. */
|
|
/* Assumig 4 times compression ratio */
|
|
base_encoder->codedbuf_size = GST_ROUND_UP_16 (vip->width) *
|
|
GST_ROUND_UP_16 (vip->height) * 12 / 4;
|
|
|
|
base_encoder->codedbuf_size +=
|
|
MAX_FRAME_TAG_SIZE + MAX_UPDATE_SEGMENTATION_SIZE +
|
|
MAX_MB_LF_ADJUSTMENTS_SIZE + MAX_QUANT_INDICES_SIZE +
|
|
MAX_TOKEN_PROB_UPDATE_SIZE + MAX_MV_PROBE_UPDATE_SIZE +
|
|
MAX_REST_OF_FRAME_HDR_SIZE;
|
|
|
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
clear_ref (GstVaapiEncoderVP8 * encoder, GstVaapiSurfaceProxy ** ref)
|
|
{
|
|
if (*ref) {
|
|
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), *ref);
|
|
*ref = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clear_references (GstVaapiEncoderVP8 * encoder)
|
|
{
|
|
clear_ref (encoder, &encoder->last_ref);
|
|
clear_ref (encoder, &encoder->golden_ref);
|
|
clear_ref (encoder, &encoder->alt_ref);
|
|
}
|
|
|
|
static void
|
|
push_reference (GstVaapiEncoderVP8 * encoder, GstVaapiSurfaceProxy * ref)
|
|
{
|
|
if (encoder->last_ref == NULL) {
|
|
encoder->golden_ref = gst_vaapi_surface_proxy_ref (ref);
|
|
encoder->alt_ref = gst_vaapi_surface_proxy_ref (ref);
|
|
} else {
|
|
clear_ref (encoder, &encoder->alt_ref);
|
|
encoder->alt_ref = encoder->golden_ref;
|
|
encoder->golden_ref = encoder->last_ref;
|
|
}
|
|
encoder->last_ref = ref;
|
|
}
|
|
|
|
static gboolean
|
|
fill_sequence (GstVaapiEncoderVP8 * encoder, GstVaapiEncSequence * sequence)
|
|
{
|
|
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
|
|
VAEncSequenceParameterBufferVP8 *const seq_param = sequence->param;
|
|
|
|
memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferVP8));
|
|
|
|
seq_param->frame_width = GST_VAAPI_ENCODER_WIDTH (encoder);
|
|
seq_param->frame_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
|
|
|
|
if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) & GST_VAAPI_RATECONTROL_CBR)
|
|
seq_param->bits_per_second = base_encoder->bitrate * 1000;
|
|
|
|
seq_param->intra_period = base_encoder->keyframe_period;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
ensure_sequence (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture)
|
|
{
|
|
GstVaapiEncSequence *sequence;
|
|
|
|
g_assert (picture);
|
|
|
|
if (picture->type != GST_VAAPI_PICTURE_TYPE_I)
|
|
return TRUE;
|
|
|
|
sequence = GST_VAAPI_ENC_SEQUENCE_NEW (VP8, encoder);
|
|
if (!sequence)
|
|
goto error;
|
|
|
|
if (!fill_sequence (encoder, sequence))
|
|
goto error;
|
|
|
|
gst_vaapi_enc_picture_set_sequence (picture, sequence);
|
|
gst_vaapi_codec_object_replace (&sequence, NULL);
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
error:
|
|
{
|
|
gst_vaapi_codec_object_replace (&sequence, NULL);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
ensure_control_rate_params (GstVaapiEncoderVP8 * encoder,
|
|
GstVaapiEncPicture * picture)
|
|
{
|
|
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
|
|
|
|
if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
|
|
return TRUE;
|
|
|
|
/* *INDENT-OFF* */
|
|
/* RateControl params */
|
|
GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder) = (VAEncMiscParameterRateControl) {
|
|
.bits_per_second = base_encoder->bitrate * 1000,
|
|
.target_percentage = 70,
|
|
/* CPB (Coded picture buffer) length in milliseconds, which
|
|
* could be provided as a property */
|
|
.window_size = 500,
|
|
.initial_qp = encoder->yac_qi,
|
|
.min_qp = 1,
|
|
};
|
|
|
|
/* HRD params */
|
|
GST_VAAPI_ENCODER_VA_HRD (encoder) = (VAEncMiscParameterHRD) {
|
|
.buffer_size = base_encoder->bitrate * 1000 * 2,
|
|
.initial_buffer_fullness = base_encoder->bitrate * 1000,
|
|
};
|
|
|
|
/* FrameRate params */
|
|
GST_VAAPI_ENCODER_VA_FRAME_RATE (encoder) = (VAEncMiscParameterFrameRate) {
|
|
.framerate = (guint) GST_VAAPI_ENCODER_FPS_D (encoder) << 16 |
|
|
GST_VAAPI_ENCODER_FPS_N (encoder),
|
|
};
|
|
/* *INDENT-ON* */
|
|
|
|
return gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture);
|
|
}
|
|
|
|
static gboolean
|
|
ensure_misc_params (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture)
|
|
{
|
|
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
|
|
|
|
if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
|
|
return FALSE;
|
|
|
|
if (!ensure_control_rate_params (encoder, picture))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fill_picture (GstVaapiEncoderVP8 * encoder,
|
|
GstVaapiEncPicture * picture,
|
|
GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
|
|
{
|
|
VAEncPictureParameterBufferVP8 *const pic_param = picture->param;
|
|
int i;
|
|
|
|
memset (pic_param, 0, sizeof (VAEncPictureParameterBufferVP8));
|
|
|
|
pic_param->reconstructed_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
|
|
pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
|
|
|
|
if (picture->type == GST_VAAPI_PICTURE_TYPE_P) {
|
|
pic_param->pic_flags.bits.frame_type = 1;
|
|
pic_param->ref_arf_frame =
|
|
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->alt_ref);
|
|
pic_param->ref_gf_frame =
|
|
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->golden_ref);
|
|
pic_param->ref_last_frame =
|
|
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->last_ref);
|
|
pic_param->pic_flags.bits.refresh_last = 1;
|
|
pic_param->pic_flags.bits.refresh_golden_frame = 0;
|
|
pic_param->pic_flags.bits.copy_buffer_to_golden = 1;
|
|
pic_param->pic_flags.bits.refresh_alternate_frame = 0;
|
|
pic_param->pic_flags.bits.copy_buffer_to_alternate = 2;
|
|
} else {
|
|
pic_param->ref_last_frame = VA_INVALID_SURFACE;
|
|
pic_param->ref_gf_frame = VA_INVALID_SURFACE;
|
|
pic_param->ref_arf_frame = VA_INVALID_SURFACE;
|
|
pic_param->pic_flags.bits.refresh_last = 1;
|
|
pic_param->pic_flags.bits.refresh_golden_frame = 1;
|
|
pic_param->pic_flags.bits.refresh_alternate_frame = 1;
|
|
}
|
|
|
|
pic_param->pic_flags.bits.show_frame = 1;
|
|
|
|
if (encoder->loop_filter_level) {
|
|
pic_param->pic_flags.bits.version = 1;
|
|
pic_param->pic_flags.bits.loop_filter_type = 1; /* Enable simple loop filter */
|
|
/* Disabled segmentation, so what matters is only loop_filter_level[0] */
|
|
for (i = 0; i < 4; i++)
|
|
pic_param->loop_filter_level[i] = encoder->loop_filter_level;
|
|
}
|
|
|
|
pic_param->sharpness_level = encoder->sharpness_level;
|
|
|
|
/* Used for CBR */
|
|
pic_param->clamp_qindex_low = 0;
|
|
pic_param->clamp_qindex_high = 127;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
ensure_picture (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture,
|
|
GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
|
|
{
|
|
GstVaapiCodedBuffer *const codedbuf =
|
|
GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
|
|
|
|
if (!fill_picture (encoder, picture, codedbuf, surface))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fill_quantization_table (GstVaapiEncoderVP8 * encoder,
|
|
GstVaapiEncPicture * picture, GstVaapiEncQMatrix * q_matrix)
|
|
{
|
|
VAQMatrixBufferVP8 *const qmatrix_param = q_matrix->param;
|
|
int i;
|
|
|
|
memset (qmatrix_param, 0, sizeof (VAQMatrixBufferVP8));
|
|
|
|
/* DefaultYacQantVal = 8 for I frame, which is ac_qlookup[4] and
|
|
* DefaultYacQantVAl = 44 for P frame, which is ac_qllookup[40] */
|
|
for (i = 0; i < 4; i++) {
|
|
if (encoder->yac_qi == DEFAULT_YAC_QI) {
|
|
if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
|
|
qmatrix_param->quantization_index[i] = 4;
|
|
else
|
|
qmatrix_param->quantization_index[i] = 40;
|
|
} else
|
|
qmatrix_param->quantization_index[i] = encoder->yac_qi;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
ensure_quantization_table (GstVaapiEncoderVP8 * encoder,
|
|
GstVaapiEncPicture * picture)
|
|
{
|
|
g_assert (picture);
|
|
|
|
picture->q_matrix = GST_VAAPI_ENC_Q_MATRIX_NEW (VP8, encoder);
|
|
if (!picture->q_matrix) {
|
|
GST_ERROR ("failed to allocate quantiser table");
|
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
|
}
|
|
|
|
if (!fill_quantization_table (encoder, picture, picture->q_matrix))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GstVaapiEncoderStatus
|
|
gst_vaapi_encoder_vp8_encode (GstVaapiEncoder * base_encoder,
|
|
GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
|
|
{
|
|
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
|
|
GstVaapiSurfaceProxy *reconstruct = NULL;
|
|
|
|
reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
|
|
|
|
g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
|
|
|
|
if (!ensure_sequence (encoder, picture))
|
|
goto error;
|
|
if (!ensure_misc_params (encoder, picture))
|
|
goto error;
|
|
if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
|
|
goto error;
|
|
if (!ensure_quantization_table (encoder, picture))
|
|
goto error;
|
|
if (!gst_vaapi_enc_picture_encode (picture))
|
|
goto error;
|
|
if (reconstruct) {
|
|
if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
|
|
clear_references (encoder);
|
|
push_reference (encoder, reconstruct);
|
|
}
|
|
|
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
|
|
/* ERRORS */
|
|
error:
|
|
{
|
|
if (reconstruct)
|
|
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
|
|
reconstruct);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
static GstVaapiEncoderStatus
|
|
gst_vaapi_encoder_vp8_flush (GstVaapiEncoder * base_encoder)
|
|
{
|
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
}
|
|
|
|
static GstVaapiEncoderStatus
|
|
gst_vaapi_encoder_vp8_reordering (GstVaapiEncoder * base_encoder,
|
|
GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
|
|
{
|
|
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
GstVaapiEncPicture *picture = NULL;
|
|
GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
|
|
if (!frame)
|
|
return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
|
|
|
|
picture = GST_VAAPI_ENC_PICTURE_NEW (VP8, encoder, frame);
|
|
if (!picture) {
|
|
GST_WARNING ("create VP8 picture failed, frame timestamp:%"
|
|
GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
|
|
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
|
}
|
|
|
|
if (encoder->frame_num >= base_encoder->keyframe_period) {
|
|
encoder->frame_num = 0;
|
|
clear_references (encoder);
|
|
}
|
|
if (encoder->frame_num == 0) {
|
|
picture->type = GST_VAAPI_PICTURE_TYPE_I;
|
|
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
|
|
} else {
|
|
picture->type = GST_VAAPI_PICTURE_TYPE_P;
|
|
}
|
|
|
|
encoder->frame_num++;
|
|
*output = picture;
|
|
return status;
|
|
}
|
|
|
|
static GstVaapiEncoderStatus
|
|
gst_vaapi_encoder_vp8_reconfigure (GstVaapiEncoder * base_encoder)
|
|
{
|
|
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
GstVaapiEncoderStatus status;
|
|
|
|
status = ensure_profile (encoder);
|
|
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
|
|
return status;
|
|
|
|
if (!ensure_bitrate (encoder))
|
|
goto error;
|
|
|
|
return set_context_info (base_encoder);
|
|
|
|
/* ERRORS */
|
|
error:
|
|
{
|
|
return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_encoder_vp8_init (GstVaapiEncoder * base_encoder)
|
|
{
|
|
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
|
|
encoder->frame_num = 0;
|
|
encoder->last_ref = NULL;
|
|
encoder->golden_ref = NULL;
|
|
encoder->alt_ref = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_encoder_vp8_finalize (GstVaapiEncoder * base_encoder)
|
|
{
|
|
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
clear_references (encoder);
|
|
}
|
|
|
|
static GstVaapiEncoderStatus
|
|
gst_vaapi_encoder_vp8_set_property (GstVaapiEncoder * base_encoder,
|
|
gint prop_id, const GValue * value)
|
|
{
|
|
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8_CAST (base_encoder);
|
|
|
|
switch (prop_id) {
|
|
case GST_VAAPI_ENCODER_VP8_PROP_LOOP_FILTER_LEVEL:
|
|
encoder->loop_filter_level = g_value_get_uint (value);
|
|
break;
|
|
case GST_VAAPI_ENCODER_VP8_PROP_SHARPNESS_LEVEL:
|
|
encoder->sharpness_level = g_value_get_uint (value);
|
|
break;
|
|
case GST_VAAPI_ENCODER_VP8_PROP_YAC_Q_INDEX:
|
|
encoder->yac_qi = g_value_get_uint (value);
|
|
break;
|
|
default:
|
|
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
|
|
}
|
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
}
|
|
|
|
GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (VP8);
|
|
|
|
static inline const GstVaapiEncoderClass *
|
|
gst_vaapi_encoder_vp8_class (void)
|
|
{
|
|
static const GstVaapiEncoderClass GstVaapiEncoderVP8Class = {
|
|
GST_VAAPI_ENCODER_CLASS_INIT (VP8, vp8),
|
|
.set_property = gst_vaapi_encoder_vp8_set_property,
|
|
};
|
|
return &GstVaapiEncoderVP8Class;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_encoder_vp8_new:
|
|
* @display: a #GstVaapiDisplay
|
|
*
|
|
* Creates a new #GstVaapiEncoder for VP8 encoding.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiEncoder object
|
|
*/
|
|
GstVaapiEncoder *
|
|
gst_vaapi_encoder_vp8_new (GstVaapiDisplay * display)
|
|
{
|
|
return gst_vaapi_encoder_new (gst_vaapi_encoder_vp8_class (), display);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_encoder_vp8_get_default_properties:
|
|
*
|
|
* Determines the set of common and vp8 specific encoder properties.
|
|
* The caller owns an extra reference to the resulting array of
|
|
* #GstVaapiEncoderPropInfo elements, so it shall be released with
|
|
* g_ptr_array_unref() after usage.
|
|
*
|
|
* Return value: the set of encoder properties for #GstVaapiEncoderVP8,
|
|
* or %NULL if an error occurred.
|
|
*/
|
|
GPtrArray *
|
|
gst_vaapi_encoder_vp8_get_default_properties (void)
|
|
{
|
|
const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_vp8_class ();
|
|
GPtrArray *props;
|
|
|
|
props = gst_vaapi_encoder_properties_get_default (klass);
|
|
if (!props)
|
|
return NULL;
|
|
|
|
GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
|
|
GST_VAAPI_ENCODER_VP8_PROP_LOOP_FILTER_LEVEL,
|
|
g_param_spec_uint ("loop-filter-level",
|
|
"Loop Filter Level",
|
|
"Controls the deblocking filter strength",
|
|
0, 63, DEFAULT_LOOP_FILTER_LEVEL,
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
|
|
GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
|
|
GST_VAAPI_ENCODER_VP8_PROP_SHARPNESS_LEVEL,
|
|
g_param_spec_uint ("sharpness-level",
|
|
"Sharpness Level",
|
|
"Controls the deblocking filter sensitivity",
|
|
0, 7, DEFAULT_SHARPNESS_LEVEL,
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
|
|
GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
|
|
GST_VAAPI_ENCODER_VP8_PROP_YAC_Q_INDEX,
|
|
g_param_spec_uint ("yac-qi",
|
|
"Luma AC Quant Table index",
|
|
"Quantization Table index for Luma AC Coefficients, (in default case, yac_qi=4 for key frames and yac_qi=40 for P frames)",
|
|
0, 127, DEFAULT_YAC_QI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
|
|
return props;
|
|
}
|