From e8c4029e5f2648d9ce896a439646e77e7055e534 Mon Sep 17 00:00:00 2001 From: Wind Yuan Date: Mon, 10 Oct 2011 10:24:02 +0800 Subject: [PATCH] extract vaapiencoder structure to make other encoders possible --- gst/vaapiencode/gsth264encode.c | 699 -------------------------------------- gst/vaapiencode/gsth264encode.h | 64 ---- gst/vaapiencode/gstvaapiencode.h | 32 +- gst/vaapiencode/h264encoder.c | 717 +++++++++++++++++---------------------- gst/vaapiencode/h264encoder.h | 90 +---- 5 files changed, 335 insertions(+), 1267 deletions(-) delete mode 100644 gst/vaapiencode/gsth264encode.c delete mode 100644 gst/vaapiencode/gsth264encode.h diff --git a/gst/vaapiencode/gsth264encode.c b/gst/vaapiencode/gsth264encode.c deleted file mode 100644 index b183605..0000000 --- a/gst/vaapiencode/gsth264encode.c +++ /dev/null @@ -1,699 +0,0 @@ -#include "gsth264encode.h" - -#include -#include - -#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 "); - -/* 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 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 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/") - - diff --git a/gst/vaapiencode/gsth264encode.h b/gst/vaapiencode/gsth264encode.h deleted file mode 100644 index 08a0fd6..0000000 --- a/gst/vaapiencode/gsth264encode.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * gstvaapidecode.h - VA-API video decoder - * - * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems - * Copyright (C) 2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef GST_H264ENCODE_H -#define GST_H264ENCODE_H - -#include -#include "h264encoder.h" - -G_BEGIN_DECLS - -#define GST_TYPE_H264ENCODE (gst_h264encode_get_type()) -#define GST_IS_H264ENCODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_H264ENCODE)) -#define GST_IS_H264ENCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_H264ENCODE)) -#define GST_H264ENCODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_H264ENCODE, GstH264EncodeClass)) -#define GST_H264ENCODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_H264ENCODE, GstH264Encode)) -#define GST_H264ENCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_H264ENCODE, GstH264EncodeClass)) - - -typedef struct _GstH264Encode GstH264Encode; -typedef struct _GstH264EncodeClass GstH264EncodeClass; - -struct _GstH264Encode { - GstElement parent_instance; - - GstPad *sinkpad; - GstCaps *sinkpad_caps; - - GstPad *srcpad; - GstCaps *srcpad_caps; - - GstH264Encoder *encoder; - gboolean first_sink_frame; - gboolean first_src_frame; -}; - -struct _GstH264EncodeClass { - GstElementClass parent_class; -}; - -GType gst_h264encode_get_type(void); - -G_END_DECLS - -#endif /* GST_H264ENCODE_H */ - diff --git a/gst/vaapiencode/gstvaapiencode.h b/gst/vaapiencode/gstvaapiencode.h index 42e13d6..d87e734 100644 --- a/gst/vaapiencode/gstvaapiencode.h +++ b/gst/vaapiencode/gstvaapiencode.h @@ -1,22 +1,22 @@ /* - * gstvaapiencode.h - VA-API video encoder + * gstvaapiencode.h - VA-API video encode * + * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems * Copyright (C) 2011 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 program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef GST_VAAPI_ENCODE_H @@ -27,13 +27,6 @@ G_BEGIN_DECLS -/* Default templates */ -#define GST_CAPS_CODEC(CODEC) \ - CODEC ", " \ - "width = (int) [ 1, MAX ], " \ - "height = (int) [ 1, MAX ]; " - - #define GST_TYPE_VAAPI_ENCODE (gst_vaapi_encode_get_type()) #define GST_IS_VAAPI_ENCODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODE)) #define GST_IS_VAAPI_ENCODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODE)) @@ -61,7 +54,6 @@ struct _GstVaapiEncode { struct _GstVaapiEncodeClass { GstElementClass parent_class; - gboolean (*set_encoder_src_caps)(GstVaapiEncode* encode, GstCaps *caps); }; GType gst_vaapi_encode_get_type(void); diff --git a/gst/vaapiencode/h264encoder.c b/gst/vaapiencode/h264encoder.c index d16d632..21bb7f1 100644 --- a/gst/vaapiencode/h264encoder.c +++ b/gst/vaapiencode/h264encoder.c @@ -11,7 +11,6 @@ #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" @@ -21,14 +20,6 @@ #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 @@ -64,14 +55,14 @@ struct _GstH264EncoderPrivate { 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; @@ -96,7 +87,7 @@ struct _GstH264EncoderPrivate { }; -G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, G_TYPE_OBJECT); +G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_ENCODER); // 4096-1 @@ -117,27 +108,36 @@ static const uint8_t h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3 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, @@ -153,7 +153,7 @@ static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h2 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); @@ -161,7 +161,7 @@ static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, int32_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); @@ -169,13 +169,26 @@ static const uint8_t *h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_ 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; @@ -189,7 +202,7 @@ gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data) 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; @@ -224,17 +237,19 @@ gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer) { 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) */ @@ -269,14 +284,14 @@ h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *vid //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; } @@ -284,7 +299,7 @@ static void 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) { } @@ -294,7 +309,7 @@ h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface) 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); @@ -304,7 +319,7 @@ h264_pop_free_surface(GstH264EncoderPrivate *h264_prv) static void h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface) { - H264_ASSERT(surface); + ENCODER_ASSERT(surface); if (!surface) { return; } @@ -312,13 +327,6 @@ h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface } -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) { @@ -349,7 +357,8 @@ static void 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 */ @@ -359,13 +368,13 @@ gst_h264_encoder_init(GstH264Encoder *encoder) 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; @@ -385,6 +394,9 @@ gst_h264_encoder_init(GstH264Encoder *encoder) 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 @@ -420,10 +432,7 @@ gst_h264_encoder_finalize(GObject *object) 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; @@ -448,9 +457,9 @@ gst_h264_encoder_init_public_values(GstH264Encoder* encoder) { 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; @@ -472,99 +481,24 @@ gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es) 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) { @@ -589,7 +523,7 @@ gst_h264_validate_parameters(GstH264Encoder *encoder) /* 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) { @@ -607,57 +541,48 @@ gst_h264_validate_parameters(GstH264Encoder *encoder) 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) { @@ -666,42 +591,37 @@ gst_h264_encoder_open(GstH264Encoder* encoder) 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) { @@ -730,7 +650,6 @@ gst_h264_encoder_close(GstH264Encoder* encoder) } h264_prv->frame_count = 0; - h264_prv->encode_state = H264_ENC_INIT; if (h264_prv->sps_data) { gst_buffer_unref(h264_prv->sps_data); @@ -743,68 +662,46 @@ gst_h264_encoder_close(GstH264Encoder* encoder) 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]); @@ -812,27 +709,28 @@ h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv) 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); @@ -846,12 +744,12 @@ h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv) } 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); @@ -863,100 +761,98 @@ h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv) 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; @@ -969,9 +865,10 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv, 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); @@ -981,10 +878,10 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv, 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; @@ -1006,7 +903,7 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv, 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 */ @@ -1018,68 +915,88 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv, } 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*/ @@ -1089,10 +1006,10 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool 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; @@ -1113,7 +1030,7 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool 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); @@ -1126,10 +1043,10 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool 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 */ @@ -1137,12 +1054,12 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool 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, @@ -1151,7 +1068,7 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv, 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; @@ -1159,32 +1076,34 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv, 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; } @@ -1200,7 +1119,7 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv, } *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; } @@ -1209,20 +1128,20 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv, #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; @@ -1241,27 +1160,27 @@ h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv, #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; @@ -1283,7 +1202,7 @@ h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv, } -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; @@ -1323,17 +1242,17 @@ h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, u } 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; } @@ -1345,13 +1264,18 @@ h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size, } -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; } @@ -1362,10 +1286,10 @@ static int draw_picture(int width, int height, 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; @@ -1381,26 +1305,23 @@ int main_test(int argc, const char* argv[]) 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; @@ -1422,14 +1343,14 @@ int main_test(int argc, const char* argv[]) } 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; @@ -1437,58 +1358,45 @@ int main_test(int argc, const char* argv[]) 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; @@ -1506,7 +1414,7 @@ gst_h264_encoder_get_avcC_codec_data(GstH264Encoder *encoder, GstBuffer **buffer /*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)); @@ -1525,18 +1433,19 @@ gst_h264_encoder_get_avcC_codec_data(GstH264Encoder *encoder, GstBuffer **buffer 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; @@ -1558,7 +1467,7 @@ gst_h264_encoder_get_nal_codec_data(GstH264Encoder *encoder, GstBuffer **buffer) 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 @@ -1584,11 +1493,11 @@ h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit 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); @@ -1599,10 +1508,10 @@ h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit ++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; } @@ -1627,12 +1536,12 @@ h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, ui 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; @@ -1641,7 +1550,7 @@ h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, ui } return TRUE; - error: + end: return FALSE; } @@ -1655,11 +1564,11 @@ h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value) ++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; } @@ -1675,10 +1584,10 @@ h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value) 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; } @@ -1707,14 +1616,14 @@ h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size) 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); @@ -1734,8 +1643,8 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p 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; @@ -1747,10 +1656,10 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p 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 */ @@ -1764,7 +1673,7 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p 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 */ @@ -1773,7 +1682,7 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p 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 */ @@ -1784,7 +1693,7 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p 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 */ @@ -1801,7 +1710,7 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p h264_bitstream_write_trailing_bits(bitstream); /* rbsp_trailing_bits */ return TRUE; - //error: + //end: //return FALSE; } @@ -1815,7 +1724,7 @@ h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size) 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); @@ -1857,7 +1766,7 @@ h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size) static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv) { - H264_ASSERT(0); + ENCODER_ASSERT(0); return TRUE; } diff --git a/gst/vaapiencode/h264encoder.h b/gst/vaapiencode/h264encoder.h index fc43522..785a3db 100644 --- a/gst/vaapiencode/h264encoder.h +++ b/gst/vaapiencode/h264encoder.h @@ -2,46 +2,13 @@ #ifndef _GST_H264_ENCODER_H_ #define _GST_H264_ENCODER_H_ -#include -#include -#include "gst/gstbuffer.h" -#include "gst/vaapi/gstvaapidisplay.h" #include "gst/vaapi/gstvaapisurfacepool.h" -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef DEBUG -#include -#define H264_ASSERT(exp) assert(exp) -#else -#define H264_ASSERT(exp) -#endif - -#define H264_NO_ERROR 0 -#define H264_MEM_ERR -1 -#define H264_DISPLAY_ERR -2 -#define H264_CONFIG_ERR -3 -#define H264_CONTEXT_ERR -3 -#define H264_STATE_ERR -4 -#define H264_ENC_RES_ERR -5 -#define H264_PICTURE_ERR -6 -#define H264_SURFACE_ERR -7 -#define H264_QUERY_STATUS_ERR -8 -#define H264_DATA_NOT_READY -9 -#define H264_DATA_ERR -10 -#define H264_PROFILE_ERR -11 -#define H264_PARAMETER_ERR -12 - - -#define H264_LOG_ERROR(...) fprintf(stdout, ## __VA_ARGS__) -#define H264_LOG_DEBUG(...) fprintf(stdout, ## __VA_ARGS__) -#define H264_LOG_INFO(...) fprintf(stdout, ## __VA_ARGS__) - - -typedef int H264Status; +#include "gstvaapiencoder.h" + +G_BEGIN_DECLS + typedef struct _GstH264Encoder GstH264Encoder; typedef struct _GstH264EncoderPrivate GstH264EncoderPrivate; typedef struct _GstH264EncoderClass GstH264EncoderClass; @@ -56,13 +23,6 @@ typedef struct _GstH264EncoderClass GstH264EncoderClass; #define GST_H264_ENCODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),GST_TYPE_H264_ENCODER,GstH264EncoderPrivate)) typedef enum { - H264_ENC_NULL, - H264_ENC_INIT, - H264_ENC_OPENED, - H264_ENC_ENCODING, -} H264_Encode_State; - -typedef enum { H264_PROFILE_BASELINE = 66, H264_PROFILE_MAIN = 77, H264_PROFILE_EXTENDED = 88, @@ -100,13 +60,13 @@ typedef enum { #define H264_DEFAULT_SLICE_NUM 1 struct _GstH264Encoder { - GObject parent; /*based on gobject*/ + GstVaapiEncoder parent; /*based on gobject*/ uint32_t profile; uint32_t level; - uint32_t width; - uint32_t height; - uint32_t frame_rate; + //uint32_t width; + //uint32_t height; + //uint32_t frame_rate; uint32_t bitrate; uint32_t intra_period; int32_t init_qp; /*default 24*/ @@ -116,7 +76,7 @@ struct _GstH264Encoder { }; struct _GstH264EncoderClass { - GObjectClass parent_class; + GstVaapiEncoderClass parent_class; }; @@ -130,39 +90,9 @@ static inline void gst_h264_encoder_unref (GstH264Encoder * encoder) void gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format); void gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es); -gboolean gst_h264_encoder_set_display(GstH264Encoder* encoder, GstVaapiDisplay *display); -GstVaapiDisplay *gst_h264_encoder_get_display(GstH264Encoder* encoder); - - -H264Status gst_h264_encoder_initialize(GstH264Encoder* encoder); -H264Status gst_h264_encoder_uninitialize(GstH264Encoder* encoder); - -gboolean gst_h264_validate_parameters(GstH264Encoder *encoder); -/**/ -#ifdef _MRST_ -H264Status gst_h264_encoder_open(GstH264Encoder* encoder, GstVaapiSurfacePool *surfaces_pool); -#else -H264Status gst_h264_encoder_open(GstH264Encoder* encoder); -#endif -H264Status gst_h264_encoder_close(GstH264Encoder* encoder); - - -H264Status gst_h264_encoder_encode(GstH264Encoder* encoder, GstBuffer *raw_pic, GList **coded_pics); -H264Status gst_h264_encoder_flush(GstH264Encoder* encoder, GList *coded_pics); - -H264_Encode_State gst_h264_encoder_get_state(GstH264Encoder* encoder); - -/*other functions*/ -char *h264_dump_bytes(const uint8_t *buf, uint32_t num); -H264Status gst_h264_encoder_get_avcC_codec_data(GstH264Encoder* encoder, GstBuffer **buffer); -H264Status gst_h264_encoder_get_nal_codec_data(GstH264Encoder* encoder, GstBuffer **buffer); - - -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /*_GST_H264_ENCODER_H_ */ -- 2.7.4