VideoEncoderVP8.cpp revision 82b428e49a70ddc051a36d2b3a25d90db79770dc
1/*
2* Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#include <string.h>
18#include <stdlib.h>
19#include "VideoEncoderLog.h"
20#include "VideoEncoderVP8.h"
21#include <va/va_tpi.h>
22#include <va/va_enc_vp8.h>
23
24VideoEncoderVP8::VideoEncoderVP8()
25    :VideoEncoderBase() {
26
27        mVideoParamsVP8.profile = 0;
28        mVideoParamsVP8.error_resilient = 0;
29        mVideoParamsVP8.num_token_partitions = 4;
30        mVideoParamsVP8.kf_auto = 0;
31        mVideoParamsVP8.kf_min_dist = 128;
32        mVideoParamsVP8.kf_max_dist = 128;
33        mVideoParamsVP8.min_qp = 0;
34        mVideoParamsVP8.max_qp = 63;
35        mVideoParamsVP8.init_qp = 26;
36        mVideoParamsVP8.rc_undershoot = 100;
37        mVideoParamsVP8.rc_overshoot = 100;
38        mVideoParamsVP8.hrd_buf_size = 1000;
39        mVideoParamsVP8.hrd_buf_initial_fullness = 500;
40        mVideoParamsVP8.hrd_buf_optimal_fullness = 600;
41        mVideoParamsVP8.max_frame_size_ratio = 0;
42
43        mVideoConfigVP8.force_kf = 0;
44        mVideoConfigVP8.refresh_entropy_probs = 0;
45        mVideoConfigVP8.value = 0;
46        mVideoConfigVP8.sharpness_level = 2;
47
48        mVideoConfigVP8ReferenceFrame.no_ref_last = 0;
49        mVideoConfigVP8ReferenceFrame.no_ref_gf = 0;
50        mVideoConfigVP8ReferenceFrame.no_ref_arf = 0;
51        mVideoConfigVP8ReferenceFrame.refresh_last = 1;
52        mVideoConfigVP8ReferenceFrame.refresh_golden_frame = 1;
53        mVideoConfigVP8ReferenceFrame.refresh_alternate_frame = 1;
54
55        mComParams.profile = VAProfileVP8Version0_3;
56}
57
58VideoEncoderVP8::~VideoEncoderVP8() {
59}
60
61Encode_Status VideoEncoderVP8::start() {
62
63    Encode_Status ret = ENCODE_SUCCESS;
64    LOG_V( "Begin\n");
65
66    ret = VideoEncoderBase::start ();
67    CHECK_ENCODE_STATUS_RETURN("VideoEncoderBase::start");
68
69    if (mComParams.rcMode == VA_RC_VCM) {
70        mRenderBitRate = false;
71    }
72
73    LOG_V( "end\n");
74    return ret;
75}
76
77
78Encode_Status VideoEncoderVP8::renderSequenceParams() {
79    Encode_Status ret = ENCODE_SUCCESS;
80    VAStatus vaStatus = VA_STATUS_SUCCESS;
81    VAEncSequenceParameterBufferVP8 vp8SeqParam = VAEncSequenceParameterBufferVP8();
82
83    LOG_V( "Begin\n");
84
85    vp8SeqParam.frame_width = mComParams.resolution.width;
86    vp8SeqParam.frame_height = mComParams.resolution.height;
87    vp8SeqParam.error_resilient = mVideoParamsVP8.error_resilient;
88    vp8SeqParam.kf_auto = mVideoParamsVP8.kf_auto;
89    vp8SeqParam.kf_min_dist = mVideoParamsVP8.kf_min_dist;
90    vp8SeqParam.kf_max_dist = mVideoParamsVP8.kf_max_dist;
91    vp8SeqParam.bits_per_second = mComParams.rcParams.bitRate;
92    memcpy(vp8SeqParam.reference_frames, mAutoRefSurfaces, sizeof(mAutoRefSurfaces) * mAutoReferenceSurfaceNum);
93
94    vaStatus = vaCreateBuffer(
95            mVADisplay, mVAContext,
96            VAEncSequenceParameterBufferType,
97            sizeof(vp8SeqParam),
98            1, &vp8SeqParam,
99            &mSeqParamBuf);
100    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
101
102    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
103    CHECK_VA_STATUS_RETURN("vaRenderPicture");
104
105    LOG_V( "End\n");
106	return ret;
107}
108
109Encode_Status VideoEncoderVP8::renderPictureParams(EncodeTask *task) {
110    Encode_Status ret = ENCODE_SUCCESS;
111    VAStatus vaStatus = VA_STATUS_SUCCESS;
112    VAEncPictureParameterBufferVP8 vp8PicParam = VAEncPictureParameterBufferVP8();
113    LOG_V( "Begin\n");
114
115    vp8PicParam.coded_buf = task->coded_buffer;
116    vp8PicParam.pic_flags.value = 0;
117    vp8PicParam.ref_flags.bits.force_kf = mVideoConfigVP8.force_kf; //0;
118    if(!vp8PicParam.ref_flags.bits.force_kf) {
119        vp8PicParam.ref_flags.bits.no_ref_last = mVideoConfigVP8ReferenceFrame.no_ref_last;
120        vp8PicParam.ref_flags.bits.no_ref_arf = mVideoConfigVP8ReferenceFrame.no_ref_arf;
121        vp8PicParam.ref_flags.bits.no_ref_gf = mVideoConfigVP8ReferenceFrame.no_ref_gf;
122    }
123    vp8PicParam.pic_flags.bits.refresh_entropy_probs = 0;
124    vp8PicParam.sharpness_level = 2;
125    vp8PicParam.pic_flags.bits.num_token_partitions = 2;
126    vp8PicParam.pic_flags.bits.refresh_last = mVideoConfigVP8ReferenceFrame.refresh_last;
127    vp8PicParam.pic_flags.bits.refresh_golden_frame = mVideoConfigVP8ReferenceFrame.refresh_golden_frame;
128    vp8PicParam.pic_flags.bits.refresh_alternate_frame = mVideoConfigVP8ReferenceFrame.refresh_alternate_frame;
129
130    vaStatus = vaCreateBuffer(
131            mVADisplay, mVAContext,
132            VAEncPictureParameterBufferType,
133            sizeof(vp8PicParam),
134            1, &vp8PicParam,
135            &mPicParamBuf);
136    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
137
138    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1);
139    CHECK_VA_STATUS_RETURN("vaRenderPicture");
140
141    LOG_V( "End\n");
142    return ret;
143}
144
145Encode_Status VideoEncoderVP8::renderRCParams(uint32_t layer_id, bool total_bitrate)
146{
147    VABufferID rc_param_buf;
148    VAStatus vaStatus = VA_STATUS_SUCCESS;
149    VAEncMiscParameterBuffer *misc_param;
150    VAEncMiscParameterRateControl *misc_rate_ctrl;
151
152    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
153                              VAEncMiscParameterBufferType,
154                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
155                              1,NULL,&rc_param_buf);
156    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
157
158    vaMapBuffer(mVADisplay, rc_param_buf,(void **)&misc_param);
159
160    misc_param->type = VAEncMiscParameterTypeRateControl;
161    misc_rate_ctrl = (VAEncMiscParameterRateControl *)misc_param->data;
162    memset(misc_rate_ctrl, 0, sizeof(*misc_rate_ctrl));
163
164    if(total_bitrate)
165        misc_rate_ctrl->bits_per_second = mComParams.rcParams.bitRate;
166    else
167    {
168        misc_rate_ctrl->rc_flags.bits.temporal_id = layer_id;
169        if(mTemporalLayerBitrateFramerate[layer_id].bitRate != 0)
170             misc_rate_ctrl->bits_per_second = mTemporalLayerBitrateFramerate[layer_id].bitRate;
171    }
172
173    misc_rate_ctrl->target_percentage = 100;
174    misc_rate_ctrl->window_size = 1000;
175    misc_rate_ctrl->initial_qp = mVideoParamsVP8.init_qp;
176    misc_rate_ctrl->min_qp = mVideoParamsVP8.min_qp;
177    misc_rate_ctrl->basic_unit_size = 0;
178    misc_rate_ctrl->max_qp = mVideoParamsVP8.max_qp;
179
180    vaUnmapBuffer(mVADisplay, rc_param_buf);
181
182    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &rc_param_buf, 1);
183    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
184    return 0;
185}
186
187Encode_Status VideoEncoderVP8::renderFrameRateParams(uint32_t layer_id, bool total_framerate)
188{
189    VABufferID framerate_param_buf;
190    VAStatus vaStatus = VA_STATUS_SUCCESS;
191    VAEncMiscParameterBuffer *misc_param;
192    VAEncMiscParameterFrameRate * misc_framerate;
193    uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
194    uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
195
196    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
197                              VAEncMiscParameterBufferType,
198                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterFrameRate),
199                              1,NULL,&framerate_param_buf);
200    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
201
202    vaMapBuffer(mVADisplay, framerate_param_buf,(void **)&misc_param);
203    misc_param->type = VAEncMiscParameterTypeFrameRate;
204    misc_framerate = (VAEncMiscParameterFrameRate *)misc_param->data;
205    memset(misc_framerate, 0, sizeof(*misc_framerate));
206
207    if(total_framerate)
208        misc_framerate->framerate = (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;
209    else
210    {
211        misc_framerate->framerate_flags.bits.temporal_id = layer_id;
212        if(mTemporalLayerBitrateFramerate[layer_id].frameRate != 0)
213            misc_framerate->framerate = mTemporalLayerBitrateFramerate[layer_id].frameRate;
214    }
215
216    vaUnmapBuffer(mVADisplay, framerate_param_buf);
217
218    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &framerate_param_buf, 1);
219    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
220
221    return 0;
222}
223
224Encode_Status VideoEncoderVP8::renderHRDParams(void)
225{
226    VABufferID hrd_param_buf;
227    VAStatus vaStatus = VA_STATUS_SUCCESS;
228    VAEncMiscParameterBuffer *misc_param;
229    VAEncMiscParameterHRD * misc_hrd;
230    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
231                              VAEncMiscParameterBufferType,
232                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterHRD),
233                              1,NULL,&hrd_param_buf);
234    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
235
236    vaMapBuffer(mVADisplay, hrd_param_buf,(void **)&misc_param);
237    misc_param->type = VAEncMiscParameterTypeHRD;
238    misc_hrd = (VAEncMiscParameterHRD *)misc_param->data;
239    memset(misc_hrd, 0, sizeof(*misc_hrd));
240    misc_hrd->buffer_size = 1000;
241    misc_hrd->initial_buffer_fullness = 500;
242    misc_hrd->optimal_buffer_fullness = 600;
243    vaUnmapBuffer(mVADisplay, hrd_param_buf);
244
245    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &hrd_param_buf, 1);
246    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
247
248    return 0;
249}
250
251Encode_Status VideoEncoderVP8::renderMaxFrameSizeParams(void)
252{
253    VABufferID max_frame_size_param_buf;
254    VAStatus vaStatus = VA_STATUS_SUCCESS;
255    VAEncMiscParameterBuffer *misc_param;
256    VAEncMiscParameterBufferMaxFrameSize * misc_maxframesize;
257    unsigned int frameRateNum = mComParams.frameRate.frameRateNum;
258    unsigned int frameRateDenom = mComParams.frameRate.frameRateDenom;
259    unsigned int frameRate = (unsigned int)(frameRateNum + frameRateDenom /2);
260    unsigned int bitRate = mComParams.rcParams.bitRate;
261
262    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
263                              VAEncMiscParameterBufferType,
264                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterHRD),
265                              1,NULL,&max_frame_size_param_buf);
266    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
267
268    vaMapBuffer(mVADisplay, max_frame_size_param_buf,(void **)&misc_param);
269    misc_param->type = VAEncMiscParameterTypeMaxFrameSize;
270    misc_maxframesize = (VAEncMiscParameterBufferMaxFrameSize *)misc_param->data;
271    memset(misc_maxframesize, 0, sizeof(*misc_maxframesize));
272    misc_maxframesize->max_frame_size = (unsigned int)((bitRate/frameRate) * mVideoParamsVP8.max_frame_size_ratio);
273    vaUnmapBuffer(mVADisplay, max_frame_size_param_buf);
274
275    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &max_frame_size_param_buf, 1);
276    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
277
278    return 0;
279}
280
281Encode_Status VideoEncoderVP8::renderLayerStructureParam(void)
282{
283    VABufferID layer_struc_buf;
284    VAStatus vaStatus = VA_STATUS_SUCCESS;
285    VAEncMiscParameterBuffer *misc_param;
286    VAEncMiscParameterTemporalLayerStructure *misc_layer_struc;
287    uint32_t i;
288
289    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
290		               VAEncMiscParameterBufferType,
291			       sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterTemporalLayerStructure),
292			       1, NULL, &layer_struc_buf);
293
294    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
295    vaMapBuffer(mVADisplay, layer_struc_buf, (void **)&misc_param);
296    misc_param->type = VAEncMiscParameterTypeTemporalLayerStructure;
297    misc_layer_struc = (VAEncMiscParameterTemporalLayerStructure *)misc_param->data;
298    memset(misc_layer_struc, 0, sizeof(*misc_layer_struc));
299
300    misc_layer_struc->number_of_layers = mComParams.numberOfLayer;
301    misc_layer_struc->periodicity = mComParams.nPeriodicity;
302    LOGE("renderLayerStructureParam misc_layer_struc->number_of_layers is %d",misc_layer_struc->number_of_layers);
303
304    for(i=0;i<mComParams.nPeriodicity;i++)
305    {
306        misc_layer_struc->layer_id[i] = mComParams.nLayerID[i];
307    }
308
309    vaUnmapBuffer(mVADisplay, layer_struc_buf);
310
311    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &layer_struc_buf, 1);
312    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
313
314    return 0;
315}
316
317
318Encode_Status VideoEncoderVP8::sendEncodeCommand(EncodeTask *task) {
319
320    Encode_Status ret = ENCODE_SUCCESS;
321    uint32_t i;
322
323    if (mFrameNum == 0) {
324        ret = renderSequenceParams();
325        ret = renderFrameRateParams(0,true);
326        ret = renderRCParams(0,true);
327        ret = renderHRDParams();
328        ret = renderMaxFrameSizeParams();
329        if(mRenderMultiTemporal)
330        {
331            ret = renderLayerStructureParam();
332            mRenderMultiTemporal = false;
333
334        }
335
336        if(mComParams.numberOfLayer > 1)
337            for(i=0;i<mComParams.numberOfLayer;i++)
338            {
339                ret = renderFrameRateParams(i, false);
340                ret = renderRCParams(i, false);
341            }
342
343        CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
344    }
345
346    if (mRenderBitRate){
347        ret = renderRCParams(0,true);
348        CHECK_ENCODE_STATUS_RETURN("renderRCParams");
349
350        mRenderBitRate = false;
351    }
352
353    if (mRenderFrameRate) {
354        ret = renderFrameRateParams(0,true);
355        CHECK_ENCODE_STATUS_RETURN("renderFrameRateParams");
356
357        mRenderFrameRate = false;
358    }
359
360    if (mRenderMaxFrameSize) {
361        ret = renderMaxFrameSizeParams();
362        CHECK_ENCODE_STATUS_RETURN("renderMaxFrameSizeParams");
363
364        mRenderMaxFrameSize = false;
365    }
366
367    ret = renderPictureParams(task);
368    CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
369
370    if(mForceKFrame) {
371        mVideoConfigVP8.force_kf = 0;//rest it as default value
372        mForceKFrame = false;
373    }
374
375    LOG_V( "End\n");
376    return ret;
377}
378
379
380Encode_Status VideoEncoderVP8::derivedSetParams(VideoParamConfigSet *videoEncParams) {
381
382	CHECK_NULL_RETURN_IFFAIL(videoEncParams);
383	VideoParamsVP8 *encParamsVP8 = reinterpret_cast <VideoParamsVP8*> (videoEncParams);
384
385	if (encParamsVP8->size != sizeof(VideoParamsVP8)) {
386		return ENCODE_INVALID_PARAMS;
387	}
388
389	mVideoParamsVP8 = *encParamsVP8;
390	return ENCODE_SUCCESS;
391}
392
393Encode_Status VideoEncoderVP8::derivedGetParams(VideoParamConfigSet *videoEncParams) {
394
395	CHECK_NULL_RETURN_IFFAIL(videoEncParams);
396	VideoParamsVP8 *encParamsVP8 = reinterpret_cast <VideoParamsVP8*> (videoEncParams);
397
398	if (encParamsVP8->size != sizeof(VideoParamsVP8)) {
399	       return ENCODE_INVALID_PARAMS;
400        }
401
402        *encParamsVP8 = mVideoParamsVP8;
403        return ENCODE_SUCCESS;
404}
405
406Encode_Status VideoEncoderVP8::derivedGetConfig(VideoParamConfigSet *videoEncConfig) {
407
408		int layer_id;
409        CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
410
411        switch (videoEncConfig->type)
412        {
413                case VideoConfigTypeVP8:{
414                        VideoConfigVP8 *encConfigVP8 =
415                                reinterpret_cast<VideoConfigVP8*> (videoEncConfig);
416
417                        if (encConfigVP8->size != sizeof(VideoConfigVP8)) {
418                                return ENCODE_INVALID_PARAMS;
419                        }
420
421                        *encConfigVP8 = mVideoConfigVP8;
422                }
423                break;
424
425                case VideoConfigTypeVP8ReferenceFrame:{
426
427                        VideoConfigVP8ReferenceFrame *encConfigVP8ReferenceFrame =
428                                reinterpret_cast<VideoConfigVP8ReferenceFrame*> (videoEncConfig);
429
430                        if (encConfigVP8ReferenceFrame->size != sizeof(VideoConfigVP8ReferenceFrame)) {
431                                return ENCODE_INVALID_PARAMS;
432                        }
433
434                        *encConfigVP8ReferenceFrame = mVideoConfigVP8ReferenceFrame;
435
436                }
437                break;
438
439                case VideoConfigTypeVP8MaxFrameSizeRatio :{
440
441                        VideoConfigVP8MaxFrameSizeRatio *encConfigVP8MaxFrameSizeRatio =
442                                reinterpret_cast<VideoConfigVP8MaxFrameSizeRatio*> (videoEncConfig);
443
444                        if (encConfigVP8MaxFrameSizeRatio->size != sizeof(VideoConfigVP8MaxFrameSizeRatio)) {
445                                return ENCODE_INVALID_PARAMS;
446                        }
447
448                        encConfigVP8MaxFrameSizeRatio->max_frame_size_ratio = mVideoParamsVP8.max_frame_size_ratio;
449                }
450                break;
451
452                default: {
453                   LOG_E ("Invalid Config Type");
454                   break;
455                }
456       }
457
458       return ENCODE_SUCCESS;
459}
460
461Encode_Status VideoEncoderVP8::derivedSetConfig(VideoParamConfigSet *videoEncConfig) {
462
463        int layer_id;
464        CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
465
466        switch (videoEncConfig->type)
467        {
468                case VideoConfigTypeVP8:{
469                        VideoConfigVP8 *encConfigVP8 =
470                                reinterpret_cast<VideoConfigVP8*> (videoEncConfig);
471
472                        if (encConfigVP8->size != sizeof(VideoConfigVP8)) {
473                                return ENCODE_INVALID_PARAMS;
474                        }
475
476                        mVideoConfigVP8 = *encConfigVP8;
477                }
478                break;
479
480                case VideoConfigTypeVP8ReferenceFrame:{
481                        VideoConfigVP8ReferenceFrame *encConfigVP8ReferenceFrame =
482                                reinterpret_cast<VideoConfigVP8ReferenceFrame*> (videoEncConfig);
483
484                        if (encConfigVP8ReferenceFrame->size != sizeof(VideoConfigVP8ReferenceFrame)) {
485                                return ENCODE_INVALID_PARAMS;
486                        }
487
488                        mVideoConfigVP8ReferenceFrame = *encConfigVP8ReferenceFrame;
489
490                }
491                break;
492
493                case VideoConfigTypeVP8MaxFrameSizeRatio:{
494                        VideoConfigVP8MaxFrameSizeRatio *encConfigVP8MaxFrameSizeRatio =
495                                reinterpret_cast<VideoConfigVP8MaxFrameSizeRatio*> (videoEncConfig);
496
497                        if (encConfigVP8MaxFrameSizeRatio->size != sizeof(VideoConfigVP8MaxFrameSizeRatio)) {
498                                return ENCODE_INVALID_PARAMS;
499                        }
500
501                        mVideoParamsVP8.max_frame_size_ratio = encConfigVP8MaxFrameSizeRatio->max_frame_size_ratio;
502                        mRenderMaxFrameSize = true;
503		}
504                break;
505
506                case VideoConfigTypeIDRRequest:{
507                        VideoParamConfigSet *encConfigVP8KFrameRequest =
508                                reinterpret_cast<VideoParamConfigSet*> (videoEncConfig);
509
510                        mVideoConfigVP8.force_kf = 1;
511                        mForceKFrame = true;
512                 }
513                 break;
514
515                default: {
516            LOG_E ("Invalid Config Type");
517            break;
518                }
519        }
520        return ENCODE_SUCCESS;
521}
522