+++ /dev/null
-#include "gsth264encode.h"
-
-#include <string.h>
-#include <X11/Xlib.h>
-
-#include "gst/vaapi/gstvaapivideobuffer.h"
-
-
-#define PACKAGE "libgsth264encode"
-#define VERSION "0.1.0"
-
-#define GST_H264_ENCODE_CHECK_STATUS(exp, err_num, err_reason, ...) \
- H264_ASSERT(exp); \
- if (!(exp)) { \
- ret_num = err_num; \
- H264_LOG_ERROR(err_reason, ## __VA_ARGS__); \
- goto finish; \
- }
-
-
-#define GST_H264ENCODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_H264ENCODE, GstH264EncodePrivate))
-
-typedef struct _GstH264EncodePrivate GstH264EncodePrivate;
-
-static const GstElementDetails gst_h264encode_details =
- GST_ELEMENT_DETAILS(
- "VA-API h264 encoder",
- "Codec/Encoder/Video",
- "A VA-API based h264 encoder",
- "Yuan Feng <feng.yuan@intel.com>");
-
-/* Default templates */
-#define GST_CAPS_CODEC(CODEC) \
- CODEC ", " \
- "width = (int) [ 1, MAX ], " \
- "height = (int) [ 1, MAX ]; "
-
-static const char gst_h264encode_sink_caps_str[] =
- GST_CAPS_CODEC("video/x-raw-yuv, " "format = (fourcc) { I420 } ")
- GST_CAPS_CODEC("video/x-raw-yuv, " "format = (fourcc) { NV12 } ")
- GST_CAPS_CODEC("video/x-vaapi-surface ")
- ;
-
-static const char gst_h264encode_src_caps_str[] =
- GST_CAPS_CODEC("video/x-h264");
-
-static GstStaticPadTemplate gst_h264encode_sink_factory =
- GST_STATIC_PAD_TEMPLATE(
- "sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS(gst_h264encode_sink_caps_str));
-
-static GstStaticPadTemplate gst_h264encode_src_factory =
- GST_STATIC_PAD_TEMPLATE(
- "src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS(gst_h264encode_src_caps_str));
-
-GST_BOILERPLATE(
- GstH264Encode,
- gst_h264encode,
- GstElement,
- GST_TYPE_ELEMENT);
-
-enum {
- PROP_0,
- PROP_PROFILE,
- PROP_LEVEL,
- PROP_BITRATE,
- PROP_INTRA_PERIOD,
- PROP_INIT_QP,
- PROP_MIN_QP,
- PROP_SLICE_NUM,
-};
-
-
-/*static extern*/
-static void gst_h264encode_finalize(GObject *object);
-static void gst_h264encode_set_property(GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec);
-static void gst_h264encode_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_h264encode_set_caps(GstPad *sink_pad, GstCaps *caps);
-static GstCaps *gst_h264encode_get_caps(GstPad *sink_pad);
-static GstFlowReturn gst_h264encode_chain(GstPad *sink_pad, GstBuffer *buf);
-static GstStateChangeReturn gst_h264encode_change_state(GstElement *element, GstStateChange transition);
-static GstFlowReturn gst_h264encode_buffer_alloc(GstPad * pad, guint64 offset, guint size,
- GstCaps * caps, GstBuffer ** buf);
-
-static char* _h264_dump_caps(GstCaps *cpas);
-static gboolean _h264_check_valid_profile(guint profile);
-static gboolean _h264_check_valid_level(guint level);
-
-
-/*gst fix functions*/
-
-static void
-gst_h264encode_base_init(gpointer klass)
-{
- GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
-
- gst_element_class_set_details(element_class, &gst_h264encode_details);
-
- /* sink pad */
- gst_element_class_add_pad_template(
- element_class,
- gst_static_pad_template_get(&gst_h264encode_sink_factory)
- );
-
- /* src pad */
- gst_element_class_add_pad_template(
- element_class,
- gst_static_pad_template_get(&gst_h264encode_src_factory)
- );
-}
-
-
-static void
-gst_h264encode_class_init(GstH264EncodeClass *klass)
-{
- GObjectClass * const object_class = G_OBJECT_CLASS(klass);
- GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
-
- object_class->finalize = gst_h264encode_finalize;
- object_class->set_property = gst_h264encode_set_property;
- object_class->get_property = gst_h264encode_get_property;
-
- g_object_class_install_property (object_class, PROP_PROFILE,
- g_param_spec_uint ("profile",
- "H264 Profile",
- "Profile supports: 66(Baseline), 77(Main), 100(High)",
- H264_PROFILE_BASELINE,
- H264_PROFILE_HIGH10,
- H264_DEFAULT_PROFILE,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_LEVEL,
- g_param_spec_uint ("level",
- "H264 level idc",
- "Level idc supports: 10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41",
- H264_LEVEL_10,
- H264_LEVEL_41,
- H264_DEFAULT_LEVEL,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_BITRATE,
- g_param_spec_uint ("bitrate",
- "H264 encoding bitrate",
- "H264 encoding bitrate, 10k~100M, (0, auto-calculate)",
- 0,
- 100*1000*1000,
- 0,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_INTRA_PERIOD,
- g_param_spec_uint ("intra-period",
- "H264 encoding intra-period",
- "H264 encoding intra-period",
- 1,
- 300,
- H264_DEFAULT_INTRA_PERIOD,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_INIT_QP,
- g_param_spec_uint ("init-qp",
- "H264 init-qp",
- "H264 init-qp",
- 1,
- 51,
- H264_DEFAULT_INIT_QP,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_MIN_QP,
- g_param_spec_uint ("min-qp",
- "H264 min-qp",
- "H264 min-qp",
- 1,
- 51,
- H264_DEFAULT_MIN_QP,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_SLICE_NUM,
- g_param_spec_uint ("slice-num",
- "H264 slice num",
- "H264 slice num",
- 1,
- 200,
- 1,
- G_PARAM_READWRITE));
-
- element_class->change_state = gst_h264encode_change_state;
-}
-
-static void
-gst_h264encode_finalize(GObject *object)
-{
- GstH264Encode * const encode = GST_H264ENCODE(object);
-
- if (encode->sinkpad_caps) {
- gst_caps_unref(encode->sinkpad_caps);
- encode->sinkpad_caps = NULL;
- }
- encode->sinkpad = NULL;
-
- if (encode->srcpad_caps) {
- gst_caps_unref(encode->srcpad_caps);
- encode->srcpad_caps = NULL;
- }
- encode->srcpad = NULL;
-
- if (encode->encoder) {
- gst_h264_encoder_close(encode->encoder);
- gst_h264_encoder_uninitialize(encode->encoder);
- gst_h264_encoder_unref(encode->encoder);
- encode->encoder = NULL;
- }
-
- G_OBJECT_CLASS(parent_class)->finalize(object);
-}
-
-static void
-gst_h264encode_init(GstH264Encode *encode, GstH264EncodeClass *klass)
-{
- GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
-
- encode->sinkpad_caps = NULL;
- encode->srcpad_caps = NULL;
- encode->first_sink_frame = TRUE;
- encode->first_src_frame = TRUE;
-
- encode->encoder = gst_h264_encoder_new();
- H264_ASSERT(encode->encoder);
-
- /*sink pad */
- encode->sinkpad = gst_pad_new_from_template(
- gst_element_class_get_pad_template(element_class, "sink"),
- "sink"
- );
- gst_pad_set_getcaps_function(encode->sinkpad, gst_h264encode_get_caps);
- gst_pad_set_setcaps_function(encode->sinkpad, gst_h264encode_set_caps);
- gst_pad_set_chain_function(encode->sinkpad, gst_h264encode_chain);
- gst_pad_set_bufferalloc_function(encode->sinkpad, gst_h264encode_buffer_alloc);
- /*gst_pad_set_event_function(encode->sinkpad, gst_h264encode_sink_event); */
- /*gst_pad_use_fixed_caps(encode->sinkpad);*/
- gst_element_add_pad(GST_ELEMENT(encode), encode->sinkpad);
-
- /* src pad */
- encode->srcpad = gst_pad_new_from_template(
- gst_element_class_get_pad_template(element_class, "src"),
- "src"
- );
- encode->srcpad_caps = NULL;
-
- gst_pad_use_fixed_caps(encode->srcpad);
- /*gst_pad_set_event_function(encode->srcpad, gst_h264encode_src_event);*/
- gst_element_add_pad(GST_ELEMENT(encode), encode->srcpad);
-}
-
-
-static void
-gst_h264encode_set_property(GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- GstH264Encode *encode = GST_H264ENCODE(object);
- H264_ASSERT(encode->encoder);
-
- switch (prop_id) {
- case PROP_PROFILE: {
- guint profile = g_value_get_uint(value);
- if (_h264_check_valid_profile(profile)) {
- encode->encoder->profile = profile;
- } else {
- H264_LOG_ERROR("h264encode set property <profile> failed.\n");
- }
- }
- break;
-
- case PROP_LEVEL: {
- guint level = g_value_get_uint(value);
- if (_h264_check_valid_level(level)) {
- encode->encoder->level= level;
- } else {
- H264_LOG_ERROR("h264encode set property <level> failed.\n");
- }
- }
- break;
-
- case PROP_BITRATE: {
- encode->encoder->bitrate = g_value_get_uint(value);
- }
- break;
-
- case PROP_INTRA_PERIOD: {
- encode->encoder->intra_period = g_value_get_uint(value);
- }
- break;
-
- case PROP_INIT_QP: {
- encode->encoder->init_qp = g_value_get_uint(value);
- }
- break;
-
- case PROP_MIN_QP: {
- encode->encoder->min_qp = g_value_get_uint(value);
- }
- break;
-
- case PROP_SLICE_NUM: {
- encode->encoder->slice_num= g_value_get_uint(value);
- }
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_h264encode_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstH264Encode *encode = GST_H264ENCODE(object);
- H264_ASSERT(encode->encoder);
-
- switch (prop_id) {
- case PROP_PROFILE:
- g_value_set_uint (value, encode->encoder->profile);
- break;
-
- case PROP_LEVEL:
- g_value_set_uint (value, encode->encoder->level);
- break;
-
- case PROP_BITRATE:
- g_value_set_uint (value, encode->encoder->bitrate);
- break;
-
- case PROP_INTRA_PERIOD:
- g_value_set_uint (value, encode->encoder->intra_period);
- break;
-
- case PROP_INIT_QP:
- g_value_set_uint (value, encode->encoder->init_qp);
- break;
-
- case PROP_MIN_QP:
- g_value_set_uint (value, encode->encoder->min_qp);
- break;
-
- case PROP_SLICE_NUM:
- g_value_set_uint (value, encode->encoder->slice_num);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_h264encode_set_caps(GstPad *sink_pad, GstCaps *caps)
-{
- GstH264Encode *encode = GST_H264ENCODE(GST_OBJECT_PARENT(sink_pad));
- GstStructure *structure;
- gint width = 0, height = 0;
- gint fps_n = 0, fps_d = 0;
- const GValue *fps_value = NULL;
- encode->sinkpad_caps = caps;
- gst_caps_ref(caps);
- H264_LOG_INFO("gst_h264encode_set_caps,\n%s", _h264_dump_caps(caps));
-
- structure = gst_caps_get_structure (caps, 0);
- if (gst_structure_get_int (structure, "width", &width)) {
- encode->encoder->width = width;
- }
- if (gst_structure_get_int (structure, "height", &height)) {
- encode->encoder->height = height;
- }
- fps_value = gst_structure_get_value (structure, "framerate");
- if (fps_value) {
- fps_n = gst_value_get_fraction_numerator (fps_value);
- fps_d = gst_value_get_fraction_denominator (fps_value);
- encode->encoder->frame_rate = fps_n/fps_d;
- }
- return TRUE;
-}
-
-static GstCaps *
-gst_h264encode_get_caps(GstPad *sink_pad)
-{
- GstCaps *caps = NULL;
- GstH264Encode * const encode = GST_H264ENCODE(GST_OBJECT_PARENT(sink_pad));
- if (encode->sinkpad_caps) {
- gst_caps_ref(encode->sinkpad_caps);
- H264_LOG_INFO("get caps,\n%s", _h264_dump_caps(encode->sinkpad_caps));
- return encode->sinkpad_caps;
- }
- caps = gst_caps_copy(gst_pad_get_pad_template_caps(sink_pad));
- return caps;
-}
-
-static GstStateChangeReturn
-gst_h264encode_change_state(GstElement *element, GstStateChange transition)
-{
- GstH264Encode * const encode = GST_H264ENCODE(element);
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
- if (ret != GST_STATE_CHANGE_SUCCESS)
- return ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY: {
- gst_h264_encoder_close(encode->encoder);
- }
- break;
- default:
- break;
- }
- return GST_STATE_CHANGE_SUCCESS;
-}
-
-
-static GstFlowReturn
-gst_h264encode_chain(GstPad *sink_pad, GstBuffer *buf)
-{
- GstFlowReturn ret_num = GST_FLOW_OK;
- GstH264Encode *encode = GST_H264ENCODE(GST_OBJECT_PARENT(sink_pad));
- H264Status h264ret = H264_NO_ERROR;
- GList *out_buffers = NULL;
- GstBuffer *tmp_buffer = NULL;
-
- static guint input_count = 0;
- static guint output_count = 0;
-
- H264_ASSERT(encode && encode->encoder);
- if (encode->first_sink_frame) {
- /* get first buffer caps and set encoder values */
- GstStructure *recv_struct, *src_struct;
- GstCaps *recv_caps = GST_BUFFER_CAPS(buf);
- gint width, height;
- GValue const *framerate, *format_value;
- gint fps_n, fps_d;
- guint32 format;
- GstVaapiSurfacePool *surface_pool = NULL;
-
- H264_LOG_INFO("gst_h264encode_chain 1st recv-buffer caps,\n%s", _h264_dump_caps(recv_caps));
-
- recv_struct = gst_caps_get_structure (recv_caps, 0);
- GST_H264_ENCODE_CHECK_STATUS(NULL != recv_caps, GST_FLOW_ERROR, "gst_h264encode_chain, 1st buffer didn't have detailed caps.\n");
- if (gst_structure_get_int (recv_struct, "width", &width)) {
- encode->encoder->width = width;
- }
- if (gst_structure_get_int (recv_struct, "height", &height)) {
- encode->encoder->height = height;
- }
- framerate = gst_structure_get_value (recv_struct, "framerate");
- if (framerate) {
- fps_n = gst_value_get_fraction_numerator (framerate);
- fps_d = gst_value_get_fraction_denominator (framerate);
- encode->encoder->frame_rate = fps_n/fps_d;
- }
- format_value = gst_structure_get_value (recv_struct, "format");
- if (format_value) {
- GST_H264_ENCODE_CHECK_STATUS(format_value && GST_TYPE_FOURCC == G_VALUE_TYPE(format_value),
- GST_FLOW_ERROR, "1st buffer caps' format type is not fourcc.\n");
- format = gst_value_get_fourcc (format_value);
- if (format) {
- gst_h264_encoder_set_input_format(encode->encoder, format);
- }
- }
-
- /*set src pad caps*/
- if (encode->srcpad_caps) {
- gst_caps_unref(encode->srcpad_caps);
- }
- encode->srcpad_caps = gst_caps_copy(gst_pad_get_pad_template_caps(encode->srcpad));
- src_struct = gst_caps_get_structure(encode->srcpad_caps, 0);
- gst_structure_set(src_struct, "width", G_TYPE_INT, width,
- "height", G_TYPE_INT, height,
- "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
-
- /*set display and initialize encoder*/
- if (GST_VAAPI_IS_VIDEO_BUFFER(buf)) {
- GstVaapiDisplay *display = NULL;
- GstVaapiVideoBuffer *video_buffer = GST_VAAPI_VIDEO_BUFFER(buf);
- H264_ASSERT(video_buffer);
- display = gst_vaapi_video_buffer_get_display(video_buffer);
- //need to get surface_pool and set to h264encoder->vaapi_context
- //(video_buffer->priv->surface_pool);
- #ifdef _MRST_
- surface_pool = GST_VAAPI_SURFACE_POOL(gst_vaapi_video_buffer_get_surface_pool(video_buffer));
- #endif
- if (display) {
- GST_H264_ENCODE_CHECK_STATUS(gst_h264_encoder_set_display(encode->encoder,display)
- , GST_FLOW_ERROR, "set display failed in gst_h264encode_chain.\n");
- }
- }
- h264ret = gst_h264_encoder_initialize(encode->encoder);
- GST_H264_ENCODE_CHECK_STATUS (H264_NO_ERROR == h264ret, GST_FLOW_ERROR, "h264_encoder_initialize failed.\n");
- #ifdef _MRST_
- h264ret = gst_h264_encoder_open(encode->encoder, surface_pool);
- #else
- h264ret = gst_h264_encoder_open(encode->encoder);
- #endif
- GST_H264_ENCODE_CHECK_STATUS (H264_NO_ERROR == h264ret, GST_FLOW_ERROR, "gst_h264_encoder_open failed.\n");
-
- encode->first_sink_frame = FALSE;
- }
-
- /*encoding frames*/
- H264_ASSERT(gst_h264_encoder_get_state(encode->encoder) >= H264_ENC_OPENED);
- ++input_count;
- H264_LOG_INFO("input %d\n", input_count);
- h264ret = gst_h264_encoder_encode(encode->encoder, buf, &out_buffers);
- GST_H264_ENCODE_CHECK_STATUS (H264_NO_ERROR == h264ret, GST_FLOW_ERROR, "h264_encoder_encode failed.\n");
-
- /*check results*/
- while (out_buffers) {
- tmp_buffer = out_buffers->data;
- out_buffers = g_list_remove(out_buffers, tmp_buffer);
- /*out_buffers = g_list_next(out_buffers);*/
- if (encode->first_src_frame) {
- GstBuffer *codec_data;
- H264_ASSERT(encode->srcpad_caps);
- /*replace codec data in src pad caps*/
- if (H264_NO_ERROR == gst_h264_encoder_get_avcC_codec_data(encode->encoder, &codec_data)) {
- gst_caps_set_simple(encode->srcpad_caps, "codec_data",GST_TYPE_BUFFER, codec_data, NULL);
- }
- gst_pad_set_caps (encode->srcpad, encode->srcpad_caps);
- GST_BUFFER_CAPS(tmp_buffer) = gst_caps_ref(encode->srcpad_caps);
- H264_LOG_INFO("gst_h264encode_chain 1st push-buffer caps,\n%s", _h264_dump_caps(encode->srcpad_caps));
- encode->first_src_frame = FALSE;
- }
- ++output_count;
- H264_LOG_INFO("output:%d, %" GST_TIME_FORMAT ", 0x%s\n",
- output_count,
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(tmp_buffer)),
- h264_dump_bytes(GST_BUFFER_DATA(tmp_buffer),
- (GST_BUFFER_SIZE(tmp_buffer) > 16? 16: GST_BUFFER_SIZE(tmp_buffer))));
- gst_pad_push(encode->srcpad, tmp_buffer);
- }
-
-finish:
- gst_mini_object_unref(GST_MINI_OBJECT(buf));
- return ret_num;
-
-}
-
-static GstFlowReturn
-gst_h264encode_buffer_alloc(GstPad * pad, guint64 offset, guint size,
- GstCaps * caps, GstBuffer ** buf)
-{
- GstH264Encode * const encode = GST_H264ENCODE(GST_OBJECT_PARENT(pad));
- GstStructure *structure = NULL;
- GstBuffer *buffer;
- GstVaapiDisplay* display = NULL;
- GstFlowReturn ret_num = GST_FLOW_ERROR;
-
- if (caps) {
- structure = gst_caps_get_structure(caps, 0);
- }
- if (!structure || gst_structure_has_name(structure, "video/x-vaapi-surface")) {
- H264_ASSERT(encode->encoder);
- display = gst_h264_encoder_get_display(encode->encoder);
- if (!display) {
- gst_h264_encoder_initialize(encode->encoder);
- display = gst_h264_encoder_get_display(encode->encoder);
- GST_H264_ENCODE_CHECK_STATUS(display, GST_FLOW_ERROR, "gst_h264_encoder_get_display failed in gst_h264encode_buffer_alloc.\n");
- }
- buffer = gst_vaapi_video_buffer_new(display);
- } else { /* video/x-raw-yuv */
- buffer = gst_buffer_new_and_alloc(size);
- }
-
- GST_H264_ENCODE_CHECK_STATUS(buffer, GST_FLOW_ERROR, "gst_h264encode_buffer_alloc failed.\n");
-
- GST_BUFFER_OFFSET (buffer) = offset;
- if (caps) {
- gst_buffer_set_caps(buffer, caps);
- }
- *buf = buffer;
- ret_num = GST_FLOW_OK;
-
-finish:
- if (display) {
- g_object_unref(display);
- }
- return ret_num;
-}
-
-static gboolean _h264_check_valid_profile(guint profile)
-{
- static const limit_profiles[] = {
- H264_PROFILE_BASELINE,
- H264_PROFILE_MAIN,
- H264_PROFILE_HIGH
- };
- guint n_profiles = sizeof(limit_profiles)/sizeof(limit_profiles[0]);
- guint i;
- for (i = 0; i < n_profiles; ++i) {
- if (limit_profiles[i] == profile)
- return TRUE;
- }
- return FALSE;
-}
-
-static gboolean _h264_check_valid_level(guint level)
-{
- static const limit_levels[] = {
- H264_LEVEL_10,
- H264_LEVEL_11,
- H264_LEVEL_12,
- H264_LEVEL_13,
- H264_LEVEL_20,
- H264_LEVEL_21,
- H264_LEVEL_22,
- H264_LEVEL_30,
- H264_LEVEL_31,
- H264_LEVEL_32,
- H264_LEVEL_40,
- H264_LEVEL_41,
- H264_LEVEL_42,
- H264_LEVEL_50,
- H264_LEVEL_51
- };
- guint n_levels = sizeof(limit_levels)/sizeof(limit_levels[0]);
- guint i;
- for (i = 0; i < n_levels; ++i) {
- if (limit_levels[i] == level)
- return TRUE;
- }
- return FALSE;
-
-}
-
-static char*
-_h264_dump_caps(GstCaps *cpas)
-{
- guint i = 0, j = 0;
- GstStructure const *structure;
- GValue const *value;
- static char caps_string[4096*5];
- char *tmp;
-
- char *cur = caps_string;
- memset(caps_string, 0, sizeof(caps_string));
- for (i = 0; i < gst_caps_get_size(cpas); i++) {
- structure = gst_caps_get_structure(cpas, i);
- const char* caps_name = gst_structure_get_name (structure);
- sprintf(cur, "cap_%02d:%s\n", i, caps_name);
- cur += strlen(cur);
-
- for (j = 0; j < gst_structure_n_fields(structure); j++) {
- const char* name = gst_structure_nth_field_name(structure, j);
- value = gst_structure_get_value(structure, name);
- tmp = gst_value_serialize(value);
- sprintf(cur, "\t%s:%s(%s)\n", name, tmp, G_VALUE_TYPE_NAME(value));
- cur += strlen(cur);
- g_free(tmp);
- }
- }
-
- return caps_string;
-}
-
-
-
-
-/* plugin register*/
-static gboolean
-h264encode_init (GstPlugin * plugin)
-{
- return gst_element_register (plugin, "vah264encode", GST_RANK_PRIMARY,
- GST_TYPE_H264ENCODE);
-}
-
-/* gstreamer looks for this structure to register mrstcamsrc */
-GST_PLUGIN_DEFINE (
- GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "vaapiencode",
- "Vaapi Encoder",
- h264encode_init,
- VERSION,
- "LGPL",
- "GStreamer",
- "http://gstreamer.net/")
-
-
#include "gst/gstclock.h"
#include "gst/gstvalue.h"
-#include "gst/vaapi/gstvaapidisplay_x11.h"
#include "gst/vaapi/gstvaapiobject.h"
#include "gst/vaapi/gstvaapiobject_priv.h"
#include "gst/vaapi/gstvaapicontext.h"
#define ENCPRV(encoder) GST_H264_ENCODER_GET_PRIVATE(encoder)
-#define H264_CHECK_STATUS(exp, err_num, err_reason, ...) \
- H264_ASSERT(exp); \
- if (!(exp)) { \
- ret = err_num; \
- H264_LOG_ERROR(err_reason, ## __VA_ARGS__); \
- goto error; \
- }
-
#define SHARE_CODED_BUF 0
#define DEFAULT_SURFACE_NUMBER 3
gboolean es_flag; /*elementary flag*/
/* private data*/
- GstVaapiDisplay *vaapi_display;
+ //GstVaapiDisplay *vaapi_display;
GstVaapiContext *vaapi_context;
GQueue *video_buffer_caches; /*not used for baseline*/
GstVaapiSurface *ref_surface; /* reference buffer*/
GstVaapiSurface *recon_surface; /* reconstruct buffer*/
- H264_Encode_State encode_state;
+ //VAAPI_Encode_State encode_state;
VABufferID seq_parameter;
VABufferID pic_parameter;
};
-G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_ENCODER);
// 4096-1
static GstBufferClass *h264_encode_buffer_parent_class = NULL;
+
+static EncoderStatus gst_h264_encoder_initialize(GstVaapiEncoder* encoder);
+static EncoderStatus gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder);
+static EncoderStatus gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data);
+static EncoderStatus gst_h264_encoder_close(GstVaapiEncoder* encoder);
+static EncoderStatus gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics);
+static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics);
+
+static gboolean gst_h264_validate_parameters(GstH264Encoder *encoder);
static void gst_h264_encoder_finalize(GObject *object);
static void gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
static VAProfile h264_get_va_profile(uint32_t profile);
-static H264Status h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv);
-static H264Status h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv);
-static H264Status h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
+static EncoderStatus h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv);
+static EncoderStatus h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv);
+static EncoderStatus h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
GstBuffer *raw_pic,
GstVaapiSurface *surface);
-static H264Status h264_prepare_encoding(GstH264EncoderPrivate *h264_prv,
+static EncoderStatus h264_prepare_encoding(GstH264EncoderPrivate *h264_prv,
GstBuffer *raw_pic, gboolean is_key,
VABufferID coded_buf);
-static H264Status h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
+static EncoderStatus h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
VASurfaceID surface_id,
gboolean is_key,
GstClockTime timestamp,
GstClockTime duration,
VABufferID *coded_buf,
GList **coded_pics);
-static H264Status
+static EncoderStatus
h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size);
static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
uint8_t *frame,
VABufferID *coded_id);
/* h264 bitstream functions */
-static void h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability);
+static void h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability);
static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size);
static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value);
static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value);
static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size);
-static void h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
+static void h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size);
static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
static gboolean h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc);
+/*other functions*/
+static EncoderStatus gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
+static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
+
+
static void
gst_h264_encoder_class_init(GstH264EncoderClass *klass)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+ GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
object_class->finalize = gst_h264_encoder_finalize;
+
+ encoder_class->initialize = gst_h264_encoder_initialize;
+ encoder_class->uninitialize = gst_h264_encoder_uninitialize;
+ encoder_class->open = gst_h264_encoder_open;
+ encoder_class->close = gst_h264_encoder_close;
+ encoder_class->encode = gst_h264_encoder_encode;
+ encoder_class->flush = gst_h264_encoder_flush;
/*
object_class->set_property = gst_h264_encoder_set_property;
object_class->get_property = gst_h264_encoder_get_property;
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
- H264_ASSERT(h264_encode_buffer_parent_class);
+ ENCODER_ASSERT(h264_encode_buffer_parent_class);
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
gst_h264_encode_buffer_finalize;
{
GstH264EncoderPrivate *h264_prv = NULL;
VABufferID* coded_id = NULL;
+ GstVaapiDisplay *display = NULL;
h264_prv = h264_buffer->encoder;
coded_id = h264_buffer->coded_id;
+ display = ENCODER_DISPLAY(h264_prv->public);
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(h264_prv->vaapi_context);
- VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(h264_prv->vaapi_context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
- H264_ASSERT(h264_prv);
- H264_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
- H264_ASSERT(h264_prv->available_code_buffers);
+ ENCODER_ASSERT(h264_prv);
+ ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
+ ENCODER_ASSERT(h264_prv->available_code_buffers);
g_mutex_lock(h264_prv->code_buffer_lock);
/*if (--(*h264_buffer->ref_coded_id) == 0) */
//ref_surface
GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
- H264_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
+ ENCODER_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
#if 0
g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
gst_buffer_ref(GST_BUFFER(video_buffer));
#endif
return ret;
- error:
+ end:
return NULL;
}
h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
{
#if 0
- H264_ASSERT(h264_prv->video_buffer_caches);
+ ENCODER_ASSERT(h264_prv->video_buffer_caches);
g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
for (h264_prv->video_buffer_caches) {
}
static GstVaapiSurface *
h264_pop_free_surface(GstH264EncoderPrivate *h264_prv)
{
- H264_ASSERT(h264_prv && h264_prv->vaapi_context);
+ ENCODER_ASSERT(h264_prv && h264_prv->vaapi_context);
/*may need lock*/
GstVaapiSurface *surface = gst_vaapi_context_get_surface(h264_prv->vaapi_context);
static void
h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface)
{
- H264_ASSERT(surface);
+ ENCODER_ASSERT(surface);
if (!surface) {
return;
}
}
-H264_Encode_State gst_h264_encoder_get_state(GstH264Encoder* encoder)
-{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- return h264_prv->encode_state;
-}
-
-
static VAProfile
h264_get_va_profile(uint32_t profile)
{
gst_h264_encoder_init(GstH264Encoder *encoder)
{
GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- H264_ASSERT(h264_prv);
+ GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
+ ENCODER_ASSERT(h264_prv);
h264_prv->public = encoder;
/* init public attributes */
h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
h264_prv->es_flag = TRUE;
- h264_prv->vaapi_display = NULL;
+ //h264_prv->vaapi_display = NULL;
h264_prv->vaapi_context= NULL;
h264_prv->ref_surface = NULL;
h264_prv->recon_surface = NULL;
h264_prv->video_buffer_caches = g_queue_new();
- h264_prv->encode_state = H264_ENC_NULL;
+ //h264_prv->encode_state = H264_ENC_NULL;
h264_prv->seq_parameter = VA_INVALID_ID;
h264_prv->pic_parameter = VA_INVALID_ID;
h264_prv->slice_parameter = VA_INVALID_ID;
h264_prv->code_buffer_cond = g_cond_new();
h264_prv->available_code_buffers = g_queue_new();
+ encoder_prv->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
+ /* encoder_prv->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
+
}
static void
g_object_unref(h264_prv->vaapi_context);
h264_prv->vaapi_context= NULL;
}
- if (h264_prv->vaapi_display) {
- g_object_unref(h264_prv->vaapi_display);
- h264_prv->vaapi_display = NULL;
- }
+
if (h264_prv->video_buffer_caches) {
g_queue_free(h264_prv->video_buffer_caches);
h264_prv->video_buffer_caches = NULL;
{
encoder->profile = 0;
encoder->level = 0;
- encoder->width = 0;
- encoder->height = 0;
- encoder->frame_rate = 0;
+ //encoder->width = 0;
+ //encoder->height = 0;
+ //encoder->frame_rate = 0;
encoder->bitrate = 0;
encoder->intra_period = 0;
encoder->init_qp = -1;
h264_prv->es_flag = es;
}
-gboolean
-gst_h264_encoder_set_display(GstH264Encoder* encoder, GstVaapiDisplay *display)
+EncoderStatus
+gst_h264_encoder_initialize(GstVaapiEncoder* encoder)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- if (display == h264_prv->vaapi_display) {
- return TRUE;
- }
-
- if (H264_ENC_INIT < h264_prv->encode_state) {
- return FALSE;
- }
- if (h264_prv->vaapi_display) {
- g_object_unref(h264_prv->vaapi_display);
- h264_prv->vaapi_display = NULL;
- }
- h264_prv->vaapi_display = g_object_ref(display);
- return TRUE;
+ return ENCODER_NO_ERROR;
}
-GstVaapiDisplay *
-gst_h264_encoder_get_display(GstH264Encoder* encoder)
+EncoderStatus
+gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- return (h264_prv->vaapi_display ? g_object_ref(h264_prv->vaapi_display) : NULL);
-}
-
+ return ENCODER_NO_ERROR;
-H264Status
-gst_h264_encoder_initialize(GstH264Encoder* encoder)
-{
- H264Status ret = H264_NO_ERROR;
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- VAStatus va_status = VA_STATUS_SUCCESS;
- int major_ver, minor_ver;
-
- /* check state */
- if (H264_ENC_INIT == h264_prv->encode_state) {
- return H264_NO_ERROR;
- }
- H264_ASSERT(H264_ENC_NULL == h264_prv->encode_state);
- if (H264_ENC_NULL != h264_prv->encode_state) {
- return H264_STATE_ERR;
- }
-
-/* create va_dpy*/
- if (!h264_prv->vaapi_display) {
- h264_prv->vaapi_display = gst_vaapi_display_x11_new(NULL);
- H264_CHECK_STATUS(h264_prv->vaapi_display, H264_DISPLAY_ERR, "gst_vaapi_display_x11_new failed.\n");
- }
-
- h264_prv->encode_state = H264_ENC_INIT;
- return H264_NO_ERROR;
-
- error:
- gst_h264_encoder_uninitialize(encoder);
- return ret;
-}
-
-H264Status
-gst_h264_encoder_uninitialize(GstH264Encoder* encoder)
-{
- H264Status ret = H264_NO_ERROR;
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
-
- /* release buffers first */
- if (H264_ENC_NULL == h264_prv->encode_state) {
- return H264_NO_ERROR;
- }
-
- if (H264_ENC_INIT < h264_prv->encode_state) {
- gst_h264_encoder_close(encoder);
- }
-
- H264_ASSERT(H264_ENC_INIT == h264_prv->encode_state);
-
- /* close va_dpy */
- if (h264_prv->vaapi_display) {
- g_object_unref(h264_prv->vaapi_display);
- h264_prv->vaapi_display = NULL;
- }
-
- h264_prv->encode_state = H264_ENC_NULL;
- return H264_NO_ERROR;
-
- //error:
- return ret;
}
gboolean
gst_h264_validate_parameters(GstH264Encoder *encoder)
{
GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- if (!encoder->width || !encoder->height || !encoder->frame_rate) {
+ if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
return FALSE;
}
if (!encoder->profile) {
/* default compress ratio 1: (4*8*1.5) */
if (!encoder->bitrate) {
- encoder->bitrate = encoder->width*encoder->height*encoder->frame_rate/4;
+ encoder->bitrate = ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4;
}
if (!encoder->slice_num) {
slice_7_height = 1
slice_8_height = 1
*/
- h264_prv->default_slice_height = (encoder->height+15)/16/encoder->slice_num;
+ h264_prv->default_slice_height = (ENCODER_HEIGHT(encoder)+15)/16/encoder->slice_num;
if (0 == h264_prv->default_slice_height) { /* special value */
h264_prv->default_slice_height = 1;
h264_prv->slice_mod_mb_num = 0;
- encoder->slice_num = (encoder->height+15)/16;
+ encoder->slice_num = (ENCODER_HEIGHT(encoder)+15)/16;
} else {
- h264_prv->slice_mod_mb_num = ((encoder->height+15)/16)%encoder->slice_num;
+ h264_prv->slice_mod_mb_num = ((ENCODER_HEIGHT(encoder)+15)/16)%encoder->slice_num;
}
return TRUE;
}
-H264Status
-#ifdef _MRST_
-gst_h264_encoder_open(GstH264Encoder* encoder, GstVaapiSurfacePool *surfaces_pool)
-#else
-gst_h264_encoder_open(GstH264Encoder* encoder)
-#endif
+EncoderStatus
+gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data)
{
- H264Status ret = H264_NO_ERROR;
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
+ GstVaapiSurfacePool *surfaces_pool = private_data;
+ GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
+ GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+
+ EncoderStatus ret = ENCODER_NO_ERROR;
VAProfile va_profile = -1;
VAEntrypoint entrypoints[5];
int num_entrypoints,slice_entrypoint;
VAConfigAttrib attrib[5];
VAStatus va_status = VA_STATUS_SUCCESS;
- /* check state */
- if (H264_ENC_OPENED == h264_prv->encode_state) {
- return H264_NO_ERROR;
- }
- H264_ASSERT(H264_ENC_INIT == h264_prv->encode_state);
- if (H264_ENC_INIT != h264_prv->encode_state) {
- return H264_STATE_ERR;
- }
-
/*check and set default values*/
- H264_CHECK_STATUS(gst_h264_validate_parameters(encoder), H264_PARAMETER_ERR, "h264encoder paramerter error.\n");
+ ENCODER_CHECK_STATUS(gst_h264_validate_parameters(h264_encoder), ENCODER_PARAMETER_ERR, "h264encoder paramerter error.\n");
- va_profile = h264_get_va_profile(encoder->profile);
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(!h264_prv->vaapi_context);
- H264_CHECK_STATUS(-1 != va_profile, H264_PROFILE_ERR, "profile(%d) is NOT supported.\n", encoder->profile);
+ va_profile = h264_get_va_profile(h264_encoder->profile);
+ ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
+ ENCODER_ASSERT(!h264_prv->vaapi_context);
+ ENCODER_CHECK_STATUS(-1 != va_profile, ENCODER_PROFILE_ERR, "profile(%d) is NOT supported.\n", h264_encoder->profile);
#ifdef _MRST_
h264_prv->vaapi_context = g_object_new(
GST_VAAPI_TYPE_CONTEXT,
- "display", h264_prv->vaapi_display,
+ "display", display,
"id", GST_VAAPI_ID(VA_INVALID_ID),
"entrypoint", gst_vaapi_entrypoint(VAEntrypointEncSlice),
- "width", h264_prv->public->width,
- "height", h264_prv->public->height,
+ "width", ENCODER_WIDTH(encoder),
+ "height", ENCODER_HEIGHT(encoder),
NULL
);
if (surfaces_pool) {
g_object_set(h264_prv->vaapi_context, "profile", gst_vaapi_profile(va_profile), NULL);
#else
- h264_prv->vaapi_context = gst_vaapi_context_new(h264_prv->vaapi_display,
+ VAAPI_UNUSED_ARG(surfaces_pool);
+ h264_prv->vaapi_context = gst_vaapi_context_new(display,
gst_vaapi_profile(va_profile),
gst_vaapi_entrypoint(VAEntrypointEncSlice),
- h264_prv->public->width,
- h264_prv->public->height);
+ ENCODER_WIDTH(encoder),
+ ENCODER_HEIGHT(encoder));
#endif
- H264_CHECK_STATUS(h264_prv->vaapi_context, H264_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
+ ENCODER_CHECK_STATUS(h264_prv->vaapi_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
ret = h264_encoder_alloc_buffers(h264_prv);
- if (H264_NO_ERROR != ret) {
- goto error;
+ if (ENCODER_NO_ERROR != ret) {
+ goto end;
}
- h264_prv->encode_state = H264_ENC_OPENED;
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
- error:
+ end:
// clear resources
gst_h264_encoder_close(encoder);
return ret;
}
-H264Status
-gst_h264_encoder_close(GstH264Encoder* encoder)
+EncoderStatus
+gst_h264_encoder_close(GstVaapiEncoder* encoder)
{
- H264Status ret = H264_NO_ERROR;
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
-
- if (H264_ENC_INIT >= h264_prv->encode_state) {
- return H264_NO_ERROR;
- }
+ GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
+ EncoderStatus ret = ENCODER_NO_ERROR;
+ GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
/* release buffers first */
- if (H264_ENC_OPENED <= h264_prv->encode_state) {
- h264_encoder_release_buffers(h264_prv);
- }
+ h264_encoder_release_buffers(h264_prv);
/*remove ref_surface*/
if (h264_prv->ref_surface) {
}
h264_prv->frame_count = 0;
- h264_prv->encode_state = H264_ENC_INIT;
if (h264_prv->sps_data) {
gst_buffer_unref(h264_prv->sps_data);
return ret;
}
-static H264Status
+static EncoderStatus
h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv)
{
- H264Status ret = H264_NO_ERROR;
+ EncoderStatus ret = ENCODER_NO_ERROR;
VAStatus va_status = VA_STATUS_SUCCESS;
+ GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
uint32_t i;
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(h264_prv->vaapi_context);
- VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(h264_prv->vaapi_context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
gboolean is_locked = FALSE;
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
is_locked = TRUE;
- /* 1. create sequence parameter set */
- {
- VAEncSequenceParameterBufferH264 seq_h264 = {0};
-
- seq_h264.level_idc = h264_prv->public->level; /* 3.0 */
- seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
- seq_h264.picture_width_in_mbs = (h264_prv->public->width+15)/16;
- seq_h264.picture_height_in_mbs = (h264_prv->public->height+15)/16;
-
- seq_h264.bits_per_second = h264_prv->public->bitrate;
- seq_h264.frame_rate = h264_prv->public->frame_rate;
- seq_h264.initial_qp = h264_prv->public->init_qp; /*qp_value; 15, 24, 26?*/
- seq_h264.min_qp = h264_prv->public->min_qp; /*1, 6, 10*/
- seq_h264.basic_unit_size = 0;
- seq_h264.intra_period = h264_prv->public->intra_period;
- seq_h264.intra_idr_period = h264_prv->public->intra_period;
-
- va_status = vaCreateBuffer(va_dpy, context_id,
- VAEncSequenceParameterBufferType,
- sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_ENC_RES_ERR, "alloc seq-buffer failed.\n");
- }
-
- /* 2. create coded buffers */
+ /* create coded buffers */
h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
{ // check width, height ????
- uint32_t codedbuf_size = (h264_prv->public->width * h264_prv->public->height * 400) / (16*16);
+ uint32_t codedbuf_size = (ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public) * 400) / (16*16);
for (i = 0; i < h264_prv->coded_buf_num; i++) {
va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
codedbuf_size, 1, NULL, &h264_prv->coded_bufs[i]);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_ENC_RES_ERR, "alloc coded buffer failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc coded buffer failed.\n");
}
}
/* unlock here */
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
is_locked = FALSE;
- H264_ASSERT(h264_prv->available_code_buffers);
+ ENCODER_ASSERT(h264_prv->available_code_buffers);
- /*3. create slice_param_buffers*/
+ /* create slice_param_buffers */
h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_prv->public->slice_num,
sizeof(h264_prv->slice_param_buffers[0]));
- /* 4. init queue available_code_buffers */
+ /* init queue available_code_buffers */
g_mutex_lock(h264_prv->code_buffer_lock);
for (i = 0; i < h264_prv->coded_buf_num; i++) {
g_queue_push_tail (h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
g_cond_signal(h264_prv->code_buffer_cond);
g_mutex_unlock(h264_prv->code_buffer_lock);
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
- error:
+ end:
if (is_locked) {
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
is_locked = FALSE;
}
return ret;
}
-static H264Status
+static EncoderStatus
h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
{
VAStatus va_status = VA_STATUS_SUCCESS;
uint32_t available_buf_count = h264_prv->coded_buf_num;
+ GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
uint32_t i;
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(h264_prv->vaapi_context);
- VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(h264_prv->vaapi_context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
/* wait for all coded buffer freed*/
g_mutex_lock(h264_prv->code_buffer_lock);
}
g_mutex_unlock(h264_prv->code_buffer_lock);
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
for (i = 0; i < h264_prv->coded_buf_num; i++) {
va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
}
va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
if (h264_prv->coded_bufs) {
g_free(h264_prv->coded_bufs);
h264_prv->slice_param_buffers = NULL;
}
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
}
-H264Status
-gst_h264_encoder_encode(GstH264Encoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
+EncoderStatus
+gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
{
- H264Status ret = H264_NO_ERROR;
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
+ GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+ GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
+
+ EncoderStatus ret = ENCODER_NO_ERROR;
gboolean is_key = FALSE;
VABufferID* coded_buf = NULL;
VAStatus va_status = VA_STATUS_SUCCESS;
VASurfaceID buffer_surface_id = VA_INVALID_SURFACE;
GstVaapiSurface *buffer_surface = NULL;
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(h264_prv->vaapi_context);
- VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(h264_prv->vaapi_context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
GstVaapiSurface *new_surface = NULL;
- H264_CHECK_STATUS(h264_prv->encode_state >= H264_ENC_OPENED, H264_STATE_ERR, "H264 encoder was not opened.\n");
- if (h264_prv->encode_state < H264_ENC_ENCODING) {
- h264_prv->encode_state = H264_ENC_ENCODING;
- }
-
if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
} else {
new_surface = h264_pop_free_surface(h264_prv);
buffer_surface = new_surface;
- H264_CHECK_STATUS(buffer_surface, H264_SURFACE_ERR, "h264_pop_free_surface failed.\n");
+ ENCODER_CHECK_STATUS(buffer_surface, ENCODER_SURFACE_ERR, "h264_pop_free_surface failed.\n");
/*input picture to h264_prv->cur_surface_index*/
va_status = h264_put_raw_buffer_to_surface(h264_prv, raw_pic, buffer_surface);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "va put buffer to surface failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "va put buffer to surface failed.\n");
}
buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
- H264_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, H264_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
+ ENCODER_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, ENCODER_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
/* begin picture, using default sid 0*/
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaBeginPicture error.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.\n");
/* set input buffers*/
- is_key = ((h264_prv->frame_count % encoder->intra_period) == 0);
+ is_key = ((h264_prv->frame_count % h264_encoder->intra_period) == 0);
/*get valid coded buffer*/
g_mutex_lock(h264_prv->code_buffer_lock);
- H264_ASSERT(h264_prv->available_code_buffers);
+ ENCODER_ASSERT(h264_prv->available_code_buffers);
while (g_queue_is_empty(h264_prv->available_code_buffers)) {
g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
}
coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
ret = h264_prepare_encoding(h264_prv, raw_pic, is_key, *coded_buf);
- if (H264_NO_ERROR != ret) {
+ if (ENCODER_NO_ERROR != ret) {
g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
}
g_mutex_unlock(h264_prv->code_buffer_lock);
- H264_CHECK_STATUS(H264_NO_ERROR == ret, H264_PICTURE_ERR, "h264_prepare_encoding failed.\n");
+ ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "h264_prepare_encoding failed.\n");
/* end picture */
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
va_status = vaEndPicture(va_dpy, context_id);
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaEndPicture error.\n");
+ GST_VAAPI_DISPLAY_UNLOCK(display);
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaEndPicture error.\n");
/*query surface result*/
ret = h264_query_encoding_status(h264_prv, buffer_surface_id,
is_key, GST_BUFFER_TIMESTAMP(raw_pic), GST_BUFFER_DURATION(raw_pic), coded_buf, coded_pics);
- if (H264_NO_ERROR != ret) {
- goto error;
+ if (ENCODER_NO_ERROR != ret) {
+ goto end;
}
h264_prv->frame_count++;
- error:
+ end:
if (new_surface) {
h264_push_free_surface(h264_prv, new_surface);
}
return ret;
}
-static H264Status
+static EncoderStatus
h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
GstBuffer *raw_pic,
GstVaapiSurface *surface)
{
- H264Status ret = H264_NO_ERROR;
+ EncoderStatus ret = ENCODER_NO_ERROR;
VAStatus va_status = VA_STATUS_SUCCESS;
VAImage surface_image;
VADisplay va_dpy;
uint32_t plane_count = 0;
uint32_t image_width = 0, image_height = 0;
uint32_t pitchy = 0, pitchu = 0, pitchv = 0;
+ GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
- H264_ASSERT(h264_prv->vaapi_display);
- va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ ENCODER_ASSERT(display);
+ va_dpy = gst_vaapi_display_get_display(display);
/*map image*/
image = gst_vaapi_surface_derive_image(surface);
gst_vaapi_image_map(image);
image_height = gst_vaapi_image_get_height(image);
/* copy buffer to surface */
- H264_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
+ ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
- y_size = h264_prv->public->width * h264_prv->public->height;
- u_size = ((h264_prv->public->width+1) >> 1) * ((h264_prv->public->height+1) >> 1);
+ y_size = ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public);
+ u_size = ((ENCODER_WIDTH(h264_prv->public)+1) >> 1) * ((ENCODER_HEIGHT(h264_prv->public)+1) >> 1);
y_src = GST_BUFFER_DATA(raw_pic);
u_src = y_src + y_size;
for (row = 0; row < image_height; row++) {
memcpy(y_dst, y_src, image_width);
y_dst += pitchy;
- y_src += h264_prv->public->width;
+ y_src += ENCODER_WIDTH(h264_prv->public);
}
if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
}
u_dst += pitchu;
- u_src += (h264_prv->public->width>>1);
- v_src += (h264_prv->public->width>>1);
+ u_src += (ENCODER_WIDTH(h264_prv->public)>>1);
+ v_src += (ENCODER_WIDTH(h264_prv->public)>>1);
}
} else if (GST_VAAPI_IMAGE_NV12 == h264_prv->format){
for (row = 0; row < image_height / 2; row++) {
memcpy(u_dst, u_src, image_width);
- u_src += h264_prv->public->width;
+ u_src += ENCODER_WIDTH(h264_prv->public);
u_dst += pitchu;
}
} else {
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
}
} else {
/* FIXME: fix this later */
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
}
/*unmap image*/
g_object_unref(image);
- error:
+ end:
return ret;
}
-static H264Status
+static EncoderStatus
h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gboolean is_key, VABufferID coded_buf)
{
- H264Status ret = H264_NO_ERROR;
+ EncoderStatus ret = ENCODER_NO_ERROR;
VAStatus va_status = VA_STATUS_SUCCESS;
+ GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
VAEncPictureParameterBufferH264 pic_h264;
VAEncSliceParameterBuffer *slice_h264 = NULL;
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(h264_prv->vaapi_context);
- VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(h264_prv->vaapi_context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
/* lock display */
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
/*handle first surface_index*/
/*only need first frame*/
- if (h264_prv->frame_count == 0) {
+ if (VA_INVALID_ID == h264_prv->seq_parameter) { /*first time*/
+ VAEncSequenceParameterBufferH264 seq_h264 = {0};
+
+ seq_h264.level_idc = h264_prv->public->level; /* 3.0 */
+ seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
+ seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_prv->public)+15)/16;
+ seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_prv->public)+15)/16;
+
+ seq_h264.bits_per_second = h264_prv->public->bitrate;
+ seq_h264.frame_rate = ENCODER_FPS(h264_prv->public);
+ seq_h264.initial_qp = h264_prv->public->init_qp; /*qp_value; 15, 24, 26?*/
+ seq_h264.min_qp = h264_prv->public->min_qp; /*1, 6, 10*/
+ seq_h264.basic_unit_size = 0;
+ seq_h264.intra_period = h264_prv->public->intra_period;
+ seq_h264.intra_idr_period = h264_prv->public->intra_period;
+
+ va_status = vaCreateBuffer(va_dpy, context_id,
+ VAEncSequenceParameterBufferType,
+ sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.\n");
va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
}
/* set pic_parameters*/
if (!h264_prv->ref_surface) {
h264_prv->ref_surface = h264_pop_free_surface(h264_prv);
- H264_CHECK_STATUS(h264_prv->ref_surface, H264_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
+ ENCODER_CHECK_STATUS(h264_prv->ref_surface, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
}
if (!h264_prv->recon_surface) {
h264_prv->recon_surface = h264_pop_free_surface(h264_prv);
- H264_CHECK_STATUS(h264_prv->recon_surface, H264_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
+ ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
}
pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface);
pic_h264.reconstructed_picture = GST_VAAPI_OBJECT_ID(h264_prv->recon_surface);
pic_h264.coded_buf = coded_buf;
- pic_h264.picture_width = h264_prv->public->width;
- pic_h264.picture_height = h264_prv->public->height;
+ pic_h264.picture_width = ENCODER_WIDTH(h264_prv->public);
+ pic_h264.picture_height = ENCODER_HEIGHT(h264_prv->public);
pic_h264.last_picture = 0; // last pic or not
if (VA_INVALID_ID != h264_prv->pic_parameter) { /* share the same pic_parameter*/
va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "creating pic-param buffer failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating pic-param buffer failed.\n");
va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "rendering pic-param buffer failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.\n");
/* set slice parameters, support multiple slices */
int i = 0;
slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
}
- H264_ASSERT(last_row_num == (h264_prv->public->height+15)/16);
+ ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_prv->public)+15)/16);
if (VA_INVALID_ID != h264_prv->slice_parameter) {
vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
h264_prv->public->slice_num,
h264_prv->slice_param_buffers,
&h264_prv->slice_parameter);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
/*after finished, set ref_surface_index, recon_surface_index */
h264_prv->ref_surface = h264_prv->recon_surface;
h264_prv->recon_surface = swap;
- error:
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ end:
+ GST_VAAPI_DISPLAY_UNLOCK(display);
return ret;
}
-static H264Status
+static EncoderStatus
h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
VASurfaceID surface_id,
gboolean is_key,
VABufferID *coded_buf,
GList **coded_pics)
{
- H264Status ret = H264_NO_ERROR;
+ EncoderStatus ret = ENCODER_NO_ERROR;
VAStatus va_status = VA_STATUS_SUCCESS;
VASurfaceStatus surface_status = 0;
VACodedBufferSegment *buf_list = NULL;
gboolean has_coded_data = FALSE;
gboolean is_locked = FALSE;
- H264_ASSERT(h264_prv->vaapi_display);
- H264_ASSERT(h264_prv->vaapi_context);
- VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
+ GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
+
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(h264_prv->vaapi_context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
//VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
- H264_ASSERT(coded_pics && *coded_pics == NULL);
+ ENCODER_ASSERT(coded_pics && *coded_pics == NULL);
/* lock display */
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
is_locked = TRUE;
va_status = vaSyncSurface(va_dpy, surface_id);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
if (VASurfaceSkipped&surface_status) {
- H264_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
+ ENCODER_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
}
va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
- H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
/*unlock display*/
if (is_locked) {
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
is_locked = FALSE;
}
}
*coded_pics = g_list_append(*coded_pics, ret_buffer);
buf_list = (VACodedBufferSegment*)buf_list->next;
- H264_ASSERT(NULL == buf_list);
+ ENCODER_ASSERT(NULL == buf_list);
has_coded_data = TRUE;
}
#endif
{ // if non-related, push back to available_code_buffers
g_mutex_lock(h264_prv->code_buffer_lock);
- GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_LOCK(display);
vaUnmapBuffer(va_dpy, *coded_buf);
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
g_cond_signal(h264_prv->code_buffer_cond);
g_mutex_unlock(h264_prv->code_buffer_lock);
}
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
- error:
+ end:
/*unlock display*/
if (is_locked) {
- GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
+ GST_VAAPI_DISPLAY_UNLOCK(display);
is_locked = FALSE;
}
return ret;
#if SHARE_CODED_BUF
ret_buffer = gst_h264_encode_buffer_new(h264_prv, coded_buf);
- H264_ASSERT(ret_buffer);
+ ENCODER_ASSERT(ret_buffer);
GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
GST_BUFFER_DATA(ret_buffer) = buf_list->buf;
GST_BUFFER_SIZE(ret_buffer) = buf_list->size;
#else
ret_buffer = gst_buffer_new();
- H264_ASSERT(ret_buffer);
+ ENCODER_ASSERT(ret_buffer);
H264Bitstream bitstream;
h264_bitstream_init(&bitstream, (frame_size+32)*8);
h264_bitstream_align(&bitstream, 0);
- H264_ASSERT(bitstream.bit_size == 0);
+ ENCODER_ASSERT(bitstream.bit_size == 0);
if (!h264_prv->es_flag) { /*nal format*/
h264_bitstream_write_byte_array(&bitstream, frame, frame_size);
- H264_ASSERT(bitstream.bit_size == frame_size*8);
+ ENCODER_ASSERT(bitstream.bit_size == frame_size*8);
} else { /* elementary format */
frame_end = frame + frame_size;
nal_start = frame;
nal_size = 0;
while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
- H264_ASSERT(nal_size);
+ ENCODER_ASSERT(nal_size);
if (!nal_size) {
nal_start += nal_size;
continue;
}
-static H264Status
+static EncoderStatus
h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size)
{
const uint8_t *end = buf + size;
}
if (!sps || !pps) {
- return H264_DATA_NOT_READY;
+ return ENCODER_DATA_NOT_READY;
}
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
}
static gboolean
h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc)
{
- H264_ASSERT(profile_idc && profile_comp && level_idc);
- H264_ASSERT(sps_size >= 4);
+ ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
+ ENCODER_ASSERT(sps_size >= 4);
if (sps_size < 4) {
return FALSE;
}
}
-H264Status
-gst_h264_encoder_flush(GstH264Encoder* encoder, GList *coded_pics)
+EncoderStatus
+gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics)
{
- H264Status ret = H264_NO_ERROR;
- //GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
+ EncoderStatus ret = ENCODER_NO_ERROR;
+ GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+ GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
+
+ h264_prv->frame_count = 0;
+ /*do we need destroy h264_prv->seq_parameter? */
- //error:
+ //end:
return ret;
}
unsigned char *V_start,
int UV_interleave, int box_width, int row_shift);
-int main_test(int argc, const char* argv[])
+int main_test(int argc, char* argv[])
{
- H264Status ret = H264_NO_ERROR;
- GstH264Encoder *encoder = NULL;
+ EncoderStatus ret = ENCODER_NO_ERROR;
+ GstVaapiEncoder *encoder = NULL;
GList *coded_pics = NULL;
GstBuffer **raw_buffer = NULL;
if (!g_thread_supported ())
g_thread_init (NULL);
- encoder = gst_h264_encoder_new();
- H264_ASSERT(encoder && ret == H264_NO_ERROR);
-
- encoder->profile = 64;
- encoder->level = 30;
- encoder->width = 1280;
- encoder->height = 720;
- encoder->frame_rate = 10;
- encoder->bitrate = 512*1000;
- encoder->intra_period = 30;
- ret = gst_h264_encoder_initialize(encoder);
- H264_ASSERT(ret == H264_NO_ERROR);
- #ifdef _MRST_
- ret = gst_h264_encoder_open(encoder, NULL);
- #else
- ret = gst_h264_encoder_open(encoder);
- #endif
- H264_ASSERT(ret == H264_NO_ERROR);
-
- uint32_t buffer_size = encoder->width * encoder->height *3 /2;
+ GstH264Encoder *h264_encoder = gst_h264_encoder_new();
+ encoder = GST_VAAPI_ENCODER(h264_encoder);
+ ENCODER_ASSERT(encoder);
+
+ h264_encoder->profile = 64;
+ h264_encoder->level = 30;
+ h264_encoder->parent.width = 1280;
+ h264_encoder->parent.height = 720;
+ h264_encoder->parent.frame_rate = 10;
+ h264_encoder->bitrate = 512*1000;
+ h264_encoder->intra_period = 30;
+ ret = gst_vaapi_encoder_initialize(encoder);
+ ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
+ ret = gst_vaapi_encoder_open(encoder, NULL);
+ ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
+
+ uint32_t buffer_size = encoder->width * encoder->width *3 /2;
uint32_t y_width = encoder->width, y_size = encoder->width * encoder->height;
uint32_t u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
uint32_t v_width = encoder->width/2;
}
FILE *fp = fopen("tmp.h264", "wb");
- H264_ASSERT(fp);
+ ENCODER_ASSERT(fp);
k = 0;
for (i = 0; i < 50; i++) {
coded_pics = NULL;
- ret = gst_h264_encoder_encode(encoder, raw_buffer[k], &coded_pics);
- H264_ASSERT(H264_NO_ERROR == ret);
+ ret = gst_vaapi_encoder_encode(encoder, raw_buffer[k], &coded_pics);
+ ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
++k;
if (k >= raw_buffer_num) k = 0;
tmp_buffer = coded_pics->data;
coded_pics = g_list_remove(coded_pics, tmp_buffer);
fwrite(GST_BUFFER_DATA(tmp_buffer), GST_BUFFER_SIZE(tmp_buffer), 1, fp);
- printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), h264_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
+ printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), vaapi_encoder_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
gst_buffer_unref(tmp_buffer);
}
}
fclose(fp);
- ret = gst_h264_encoder_close(encoder);
- H264_ASSERT(H264_NO_ERROR == ret);
+ ret = gst_vaapi_encoder_close(encoder);
+ ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
for (i = 0; i < raw_buffer_num; i++) {
gst_buffer_unref(raw_buffer[i]);
}
g_free(raw_buffer);
- gst_h264_encoder_unref(encoder);
+ gst_vaapi_encoder_unref(encoder);
return 0;
}
-char *h264_dump_bytes(const uint8_t *buf, uint32_t num)
-{
- static char tmp[1024];
- uint32_t i = 0;
- memset(tmp, 0, sizeof(tmp));
-
- char *p = tmp;
- for (i = 0; i < num; i++) {
- snprintf(p, 1024-(p-tmp), "%02x", (uint8_t)buf[i]);
- p += strlen(p);
- }
- return tmp;
-}
-
-H264Status
-gst_h264_encoder_get_avcC_codec_data(GstH264Encoder *encoder, GstBuffer **buffer)
+EncoderStatus
+gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
+ GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
GstBuffer *avc_codec;
const uint32_t configuration_version = 0x01;
const uint32_t length_size_minus_one = 0x03;
uint32_t profile, profile_comp, level_idc;
- H264_ASSERT(buffer);
+ ENCODER_ASSERT(buffer);
if (!h264_prv->sps_data || !h264_prv->pps_data) {
- return H264_DATA_NOT_READY;
+ return ENCODER_DATA_NOT_READY;
}
if (FALSE == h264_read_sps_attributes(GST_BUFFER_DATA(h264_prv->sps_data),
GST_BUFFER_SIZE(h264_prv->sps_data),
&profile, &profile_comp, &level_idc))
{
- H264_ASSERT(0);
- return H264_DATA_ERR;
+ ENCODER_ASSERT(0);
+ return ENCODER_DATA_ERR;
}
H264Bitstream bitstream;
/*write sps*/
h264_bitstream_write_uint(&bitstream, 1, 5); /* sps count = 1*/
- H264_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
+ ENCODER_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->sps_data), 16);
h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
GST_BUFFER_SIZE(h264_prv->sps_data));
h264_bitstream_destroy(&bitstream, FALSE);
*buffer = avc_codec;
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
}
-H264Status
-gst_h264_encoder_get_nal_codec_data(GstH264Encoder *encoder, GstBuffer **buffer)
+EncoderStatus
+gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
+ GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
GstBuffer *nal_sps_pps;
- H264_ASSERT(buffer);
+ ENCODER_ASSERT(buffer);
if (!h264_prv->sps_data || !h264_prv->pps_data) {
- return H264_DATA_NOT_READY;
+ return ENCODER_DATA_NOT_READY;
}
H264Bitstream bitstream;
GST_BUFFER_SIZE(nal_sps_pps) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
h264_bitstream_destroy(&bitstream, FALSE);
*buffer = nal_sps_pps;
- return H264_NO_ERROR;
+ return ENCODER_NO_ERROR;
}
static void
return TRUE;
}
- H264_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
+ ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
byte_pos = (bitstream->bit_size>>3);
bit_offset = (bitstream->bit_size&0x07);
cur_byte = bitstream->buffer + byte_pos;
- H264_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
+ ENCODER_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
while (bit_size) {
fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
++cur_byte;
bit_offset = 0;
}
- H264_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
+ ENCODER_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
return TRUE;
- error:
+ end:
return FALSE;
}
if (!byte_size) {
return 0;
}
- H264_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
+ ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
if (0 == (bitstream->bit_size&0x07)) {
memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
bitstream->bit_size += (byte_size<<3);
} else {
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
while(byte_size) {
h264_bitstream_write_uint(bitstream, *buf, 8);
--byte_size;
}
return TRUE;
- error:
+ end:
return FALSE;
}
++size_in_bits;
tmp_value >>= 1;
}
- H264_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
- H264_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
+ ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
+ ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
return TRUE;
- error:
+ end:
return FALSE;
}
new_val = (value<<1) - 1;
}
- H264_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
+ ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
return TRUE;
- error:
+ end:
return FALSE;
}
uint32_t new_bit_size = extra_bit_size + bitstream->bit_size;
uint32_t clear_pos;
- H264_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
+ ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
if (new_bit_size <= bitstream->max_bit_capability) {
return TRUE;
}
new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
&(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
- H264_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
+ ENCODER_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
clear_pos = ((bitstream->bit_size+7)>>3);
bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0; // 2 ? 4?
uint32_t num_ref_frames = 1; // only P frames
uint32_t gaps_in_frame_num_value_allowed_flag = 0; // ??
- uint32_t mb_width = (h264_prv->public->width+15)/16; // mb_width
- uint32_t mb_height = (h264_prv->public->height+15)/16; // mb_height
+ uint32_t mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
+ uint32_t mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
int32_t frame_mbs_only_flag = 1; // only mbs
uint32_t frame_cropping_flag = 0;
uint32_t frame_crop_bottom_offset = 0;
constraint_set2_flag = 0;
constraint_set3_flag = 0;
- if (mb_height * 16 - h264_prv->public->height) {
+ if (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) {
frame_cropping_flag = 1;
frame_crop_bottom_offset =
- (mb_height * 16 - h264_prv->public->height) / (2 * (!frame_mbs_only_flag + 1));
+ (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) / (2 * (!frame_mbs_only_flag + 1));
}
h264_bitstream_write_uint(bitstream, h264_prv->public->profile, 8); /* profile_idc */
if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
/* FIXME: fix for high profile */
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
}
h264_bitstream_write_ue(bitstream, log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
if (pic_order_cnt_type == 0)
h264_bitstream_write_ue(bitstream, log2_max_pic_order_cnt_lsb_minus4);/* log2_max_pic_order_cnt_lsb_minus4 */
else {
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
}
h264_bitstream_write_ue(bitstream, num_ref_frames); /* num_ref_frames */
h264_bitstream_write_uint(bitstream, frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
if (!frame_mbs_only_flag) { //ONLY mbs
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
}
h264_bitstream_write_uint(bitstream, 0, 1); /* direct_8x8_inference_flag */
h264_bitstream_write_trailing_bits(bitstream); /* rbsp_trailing_bits */
return TRUE;
- //error:
+ //end:
//return FALSE;
}
uint32_t flag = 0xFFFFFFFF;
uint32_t nal_start_len = 0;
- H264_ASSERT(len >= 0 && buffer && nal_size);
+ ENCODER_ASSERT(len >= 0 && buffer && nal_size);
if (len < 3) {
*nal_size = len;
nal_start = (len ? buffer : NULL);
static gboolean
h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
{
- H264_ASSERT(0);
+ ENCODER_ASSERT(0);
return TRUE;
}