encoder(h264,h263,mpeg4): changed styles, names
[vaapi:windyuan-gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapiencoder_h263.c
1 /*
2  *  gstvaapiencoder_h263.c - H.263 encoder
3  *
4  *  Copyright (C) 2011 Intel Corporation
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public License
8  *  as published by the Free Software Foundation; either version 2.1
9  *  of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301 USA
20  */
21
22 #include "gstvaapiencoder_h263.h"
23
24 #include <string.h>
25 #include <gst/gstclock.h>
26
27 #include "gst/vaapi/gstvaapiobject.h"
28 #include "gst/vaapi/gstvaapiobject_priv.h"
29 #include "gst/vaapi/gstvaapicontext.h"
30 #include "gst/vaapi/gstvaapisurface.h"
31 #include "gst/vaapi/gstvaapivideobuffer.h"
32 #include "gst/vaapi/gstvaapidisplay_priv.h"
33
34 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h263_encoder_debug);
35 #define GST_CAT_DEFAULT gst_vaapi_h263_encoder_debug
36
37 struct _GstVaapiEncoderH263Private {
38   GstVaapiSurface  *ref_surface;  /* reference buffer*/
39   GstVaapiSurface  *recon_surface; /* reconstruct buffer*/
40
41   VABufferID        seq_parameter;
42   VABufferID        pic_parameter;
43   VABufferID        slice_parameter;
44 };
45
46 G_DEFINE_TYPE(GstVaapiEncoderH263, gst_vaapi_encoder_h263, GST_TYPE_VAAPI_BASE_ENCODER);
47
48 /*
49 static EncoderStatus gst_vaapi_encoder_h263_flush(GstVaapiEncoder* encoder,
50                             GstVaapiDisplay *display, GstVaapiContext *context,
51                             GList **coded_pics);
52 */
53
54 static void          gst_vaapi_encoder_h263_class_init(GstVaapiEncoderH263Class *klass);
55 static void          gst_vaapi_encoder_h263_init(GstVaapiEncoderH263 *encoder);
56 static void          gst_vaapi_encoder_h263_finalize(GObject *object);
57
58 static gboolean      gst_h263_validate_parameters(GstVaapiBaseEncoder* encoder);
59 static gboolean      gst_vaapi_encoder_h263_release_resource(
60                             GstVaapiBaseEncoder* encoder, GstVaapiDisplay *display,
61                             GstVaapiContext *context);
62 static EncoderStatus gst_vaapi_encoder_h263_rendering(GstVaapiBaseEncoder *encoder,
63                             GstVaapiDisplay *display, GstVaapiContext *context,
64                             GstVaapiSurface *surface, guint frame_index,
65                             VABufferID coded_buf, gboolean *is_key);
66
67 GstVaapiEncoderH263 *
68 gst_vaapi_encoder_h263_new(void)
69 {
70   return GST_VAAPI_ENCODER_H263(g_object_new(GST_TYPE_VAAPI_ENCODER_H263, NULL));
71 }
72
73
74 static void
75 gst_vaapi_encoder_h263_class_init(GstVaapiEncoderH263Class *klass)
76 {
77   GObjectClass * const object_class = G_OBJECT_CLASS(klass);
78   GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
79   GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
80   g_type_class_add_private(klass, sizeof(GstVaapiEncoderH263Private));
81
82   GST_DEBUG_CATEGORY_INIT (gst_vaapi_h263_encoder_debug, "gst_va_h263_encoder", 0,
83       "gst_va_h263_encoder element");
84
85   object_class->finalize = gst_vaapi_encoder_h263_finalize;
86
87   base_class->validate_attributes = gst_h263_validate_parameters;
88   base_class->pre_alloc_resource  = NULL;
89   base_class->release_resource    = gst_vaapi_encoder_h263_release_resource;
90   base_class->render_frame = gst_vaapi_encoder_h263_rendering;
91   base_class->notify_frame = NULL;
92   base_class->copy_coded_frame = NULL;
93
94   /*
95   encoder_class->flush = gst_vaapi_encoder_h263_flush;
96   */
97   encoder_class->get_codec_data = NULL;
98
99 }
100
101 static void
102 gst_vaapi_encoder_h263_init(GstVaapiEncoderH263 *h263_encoder)
103 {
104   GstVaapiEncoderH263Private *h263_prv = GST_VAAPI_ENCODER_H263_GET_PRIVATE(h263_encoder);
105   ENCODER_ASSERT(h263_prv);
106
107   /* init public */
108   h263_encoder->bitrate = 0;
109   h263_encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
110   h263_encoder->init_qp = H263_DEFAULT_INIT_QP;
111   h263_encoder->min_qp = H263_DEFAULT_MIN_QP;
112
113   /* init private */
114   h263_prv->ref_surface = NULL;
115   h263_prv->recon_surface = NULL;
116
117   h263_prv->seq_parameter = VA_INVALID_ID;
118   h263_prv->pic_parameter = VA_INVALID_ID;
119   h263_prv->slice_parameter = VA_INVALID_ID;
120 }
121
122 static void
123 gst_vaapi_encoder_h263_finalize(GObject *object)
124 {
125   /*free private buffers*/
126   GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
127
128   if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
129     gst_vaapi_encoder_uninitialize(encoder);
130   }
131   G_OBJECT_CLASS(gst_vaapi_encoder_h263_parent_class)->finalize(object);
132 }
133
134 static gboolean
135 gst_h263_validate_parameters(GstVaapiBaseEncoder* encoder)
136 {
137   GstVaapiEncoderH263 *h263_encoder = GST_VAAPI_ENCODER_H263(encoder);
138   if (!ENCODER_WIDTH(h263_encoder) || !ENCODER_HEIGHT(h263_encoder) || !ENCODER_FPS(h263_encoder)) {
139     return FALSE;
140   }
141   if (!h263_encoder->intra_period) {
142     h263_encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
143   }
144   if (-1 == h263_encoder->init_qp) {
145     h263_encoder->init_qp = H263_DEFAULT_INIT_QP;
146   }
147   if (-1 == h263_encoder->min_qp) {
148     h263_encoder->min_qp = H263_DEFAULT_MIN_QP;
149   }
150
151   /* default compress ratio 1: (4*8*1.5) */
152   if (!h263_encoder->bitrate) {
153     h263_encoder->bitrate = ENCODER_WIDTH(h263_encoder)*ENCODER_HEIGHT(h263_encoder)*ENCODER_FPS(h263_encoder)/4;
154   }
155   gst_vaapi_base_encoder_set_va_profile(GST_VAAPI_BASE_ENCODER(h263_encoder), VAProfileH263Baseline);
156   return TRUE;
157
158 }
159
160
161 static void
162 h263_release_parameters(GstVaapiEncoderH263 *h263_encoder, GstVaapiDisplay *display)
163 {
164   GstVaapiEncoderH263Private *h263_prv = GST_VAAPI_ENCODER_H263_GET_PRIVATE(h263_encoder);
165   VADisplay va_dpy = gst_vaapi_display_get_display(display);
166   VAStatus va_status = VA_STATUS_SUCCESS;
167
168   VAAPI_UNUSED_ARG(va_status);
169
170   if (VA_INVALID_ID != h263_prv->seq_parameter) {
171     va_status = vaDestroyBuffer(va_dpy, h263_prv->seq_parameter);
172     h263_prv->seq_parameter = VA_INVALID_ID;
173   }
174   if (VA_INVALID_ID != h263_prv->pic_parameter) {
175     va_status = vaDestroyBuffer(va_dpy, h263_prv->pic_parameter);
176     h263_prv->pic_parameter = VA_INVALID_ID;
177   }
178   if (VA_INVALID_ID != h263_prv->slice_parameter) {
179     va_status = vaDestroyBuffer(va_dpy, h263_prv->slice_parameter);
180     h263_prv->slice_parameter = VA_INVALID_ID;
181   }
182
183 }
184
185 static gboolean
186 gst_vaapi_encoder_h263_release_resource(GstVaapiBaseEncoder* encoder,
187                        GstVaapiDisplay *display,
188                        GstVaapiContext *context)
189 {
190   GstVaapiEncoderH263 *h263_encoder = GST_VAAPI_ENCODER_H263(encoder);
191   GstVaapiEncoderH263Private *h263_prv = GST_VAAPI_ENCODER_H263_GET_PRIVATE(h263_encoder);
192
193   h263_release_parameters(h263_encoder, display);
194
195   /*remove ref_surface*/
196   if (h263_prv->ref_surface) {
197     if (context) {
198       gst_vaapi_context_put_surface(context, h263_prv->ref_surface);
199     } else {
200       g_object_unref(h263_prv->ref_surface);
201     }
202     h263_prv->ref_surface = NULL;
203   }
204
205   /*remove recon_surface*/
206   if (h263_prv->recon_surface) {
207     if (context) {
208       gst_vaapi_context_put_surface(context, h263_prv->recon_surface);
209     } else {
210       g_object_unref(h263_prv->recon_surface);
211     }
212     h263_prv->recon_surface = NULL;
213   }
214
215   return TRUE;
216 }
217
218 static EncoderStatus
219 gst_vaapi_encoder_h263_rendering(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display,
220                      GstVaapiContext *context, GstVaapiSurface *surface,
221                      guint frame_index, VABufferID coded_buf, gboolean *is_key)
222
223 {
224   GstVaapiEncoderH263 *h263_encoder = GST_VAAPI_ENCODER_H263(encoder);
225   GstVaapiEncoderH263Private *h263_prv = GST_VAAPI_ENCODER_H263_GET_PRIVATE(h263_encoder);
226   VADisplay va_dpy = gst_vaapi_display_get_display(display);
227   VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
228
229   VAStatus va_status = VA_STATUS_SUCCESS;
230   EncoderStatus ret = ENCODER_NO_ERROR;
231
232   *is_key = (frame_index % h263_encoder->intra_period == 0);
233
234   /* initialize sequence parameter set, only first time */
235   if (VA_INVALID_ID == h263_prv->seq_parameter) { /*only the first time*/
236     VAEncSequenceParameterBufferH263 seq_h263 = {0};
237
238     seq_h263.intra_period = h263_encoder->intra_period;
239     seq_h263.bits_per_second = h263_encoder->bitrate;
240     seq_h263.frame_rate = ENCODER_FPS(h263_encoder);
241     seq_h263.initial_qp = h263_encoder->init_qp;
242     seq_h263.min_qp = h263_encoder->min_qp;
243
244     va_status = vaCreateBuffer(va_dpy, context_id,
245                                VAEncSequenceParameterBufferType,
246                                sizeof(seq_h263), 1, &seq_h263, &h263_prv->seq_parameter);
247     ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "h263 alloc seq-buffer failed.");
248     va_status = vaRenderPicture(va_dpy, context_id, &h263_prv->seq_parameter, 1);
249     ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "h263 vaRenderPicture seq-parameters failed.");
250   }
251
252   /* set reference and reconstructed surfaces */
253   if (!h263_prv->ref_surface) {
254     h263_prv->ref_surface = gst_vaapi_context_get_surface(context);
255     ENCODER_CHECK_STATUS(h263_prv->ref_surface, ENCODER_SURFACE_ERR, "h263 reference surface, h263_pop_free_surface failed.");
256   }
257   if (!h263_prv->recon_surface) {
258     h263_prv->recon_surface = gst_vaapi_context_get_surface(context);
259     ENCODER_CHECK_STATUS(h263_prv->recon_surface, ENCODER_SURFACE_ERR, "h263 reconstructed surface, h263_pop_free_surface failed.");
260   }
261
262   /* initialize picture, every time, every frame */
263   VAEncPictureParameterBufferH263 pic_h263 = {0};
264   pic_h263.reference_picture = GST_VAAPI_OBJECT_ID(h263_prv->ref_surface);
265   pic_h263.reconstructed_picture = GST_VAAPI_OBJECT_ID(h263_prv->recon_surface);
266   pic_h263.coded_buf = coded_buf;
267   pic_h263.picture_width = ENCODER_WIDTH(h263_encoder);
268   pic_h263.picture_height = ENCODER_HEIGHT(h263_encoder);
269   pic_h263.picture_type = (*is_key) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
270   if (VA_INVALID_ID != h263_prv->pic_parameter) { /* destroy first*/
271     va_status = vaDestroyBuffer(va_dpy, h263_prv->pic_parameter);
272     h263_prv->pic_parameter = VA_INVALID_ID;
273   }
274
275   va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
276                                sizeof(pic_h263), 1, &pic_h263, &h263_prv->pic_parameter);
277   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
278                        ENCODER_ENC_RES_ERR, "h263 creating pic-param buffer failed.");
279   va_status = vaRenderPicture(va_dpy, context_id, &h263_prv->pic_parameter, 1);
280   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
281                        ENCODER_PICTURE_ERR, "h263 rendering pic-param buffer failed.");
282   /*initialize slice parameters, only ONE slice for h263*/
283   VAEncSliceParameterBuffer slice_h263 = { 0 };
284   slice_h263.start_row_number = 0;
285   slice_h263.slice_height = (ENCODER_HEIGHT(h263_encoder)+15)/16; /*MB?*/
286   slice_h263.slice_flags.bits.is_intra = *is_key;
287   slice_h263.slice_flags.bits.disable_deblocking_filter_idc = 0;
288   if (VA_INVALID_ID != h263_prv->slice_parameter) {
289     vaDestroyBuffer(va_dpy, h263_prv->slice_parameter);
290     h263_prv->slice_parameter = VA_INVALID_ID;
291   }
292
293   va_status = vaCreateBuffer(va_dpy,
294                              context_id,
295                              VAEncSliceParameterBufferType,
296                              sizeof(slice_h263),
297                              1,
298                              &slice_h263,
299                              &h263_prv->slice_parameter);
300   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
301                        ENCODER_ENC_RES_ERR,
302                        "h263 creating slice-parameters buffer failed.");
303
304   va_status = vaRenderPicture(va_dpy, context_id, &h263_prv->slice_parameter, 1);
305   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
306                        ENCODER_PICTURE_ERR,
307                        "h263 rendering slice-parameters buffer failed.");
308
309   /*swap ref_surface and recon_surface */
310   GstVaapiSurface *swap = h263_prv->ref_surface;
311   h263_prv->ref_surface = h263_prv->recon_surface;
312   h263_prv->recon_surface = swap;
313
314 end:
315   return ret;
316 }
317