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 24 VideoEncoderVP8::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 58 VideoEncoderVP8::~VideoEncoderVP8() { 59 } 60 61 Encode_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 78 Encode_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 109 Encode_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 145 Encode_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 187 Encode_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 224 Encode_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 251 Encode_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 281 Encode_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 318 Encode_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 380 Encode_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 393 Encode_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 406 Encode_Status VideoEncoderVP8::derivedGetConfig(VideoParamConfigSet *videoEncConfig) { 407 408 CHECK_NULL_RETURN_IFFAIL(videoEncConfig); 409 410 switch (videoEncConfig->type) 411 { 412 case VideoConfigTypeVP8:{ 413 VideoConfigVP8 *encConfigVP8 = 414 reinterpret_cast<VideoConfigVP8*> (videoEncConfig); 415 416 if (encConfigVP8->size != sizeof(VideoConfigVP8)) { 417 return ENCODE_INVALID_PARAMS; 418 } 419 420 *encConfigVP8 = mVideoConfigVP8; 421 } 422 break; 423 424 case VideoConfigTypeVP8ReferenceFrame:{ 425 426 VideoConfigVP8ReferenceFrame *encConfigVP8ReferenceFrame = 427 reinterpret_cast<VideoConfigVP8ReferenceFrame*> (videoEncConfig); 428 429 if (encConfigVP8ReferenceFrame->size != sizeof(VideoConfigVP8ReferenceFrame)) { 430 return ENCODE_INVALID_PARAMS; 431 } 432 433 *encConfigVP8ReferenceFrame = mVideoConfigVP8ReferenceFrame; 434 435 } 436 break; 437 438 case VideoConfigTypeVP8MaxFrameSizeRatio :{ 439 440 VideoConfigVP8MaxFrameSizeRatio *encConfigVP8MaxFrameSizeRatio = 441 reinterpret_cast<VideoConfigVP8MaxFrameSizeRatio*> (videoEncConfig); 442 443 if (encConfigVP8MaxFrameSizeRatio->size != sizeof(VideoConfigVP8MaxFrameSizeRatio)) { 444 return ENCODE_INVALID_PARAMS; 445 } 446 447 encConfigVP8MaxFrameSizeRatio->max_frame_size_ratio = mVideoParamsVP8.max_frame_size_ratio; 448 } 449 break; 450 451 default: { 452 LOG_E ("Invalid Config Type"); 453 break; 454 } 455 } 456 457 return ENCODE_SUCCESS; 458 } 459 460 Encode_Status VideoEncoderVP8::derivedSetConfig(VideoParamConfigSet *videoEncConfig) { 461 462 CHECK_NULL_RETURN_IFFAIL(videoEncConfig); 463 464 switch (videoEncConfig->type) 465 { 466 case VideoConfigTypeVP8:{ 467 VideoConfigVP8 *encConfigVP8 = 468 reinterpret_cast<VideoConfigVP8*> (videoEncConfig); 469 470 if (encConfigVP8->size != sizeof(VideoConfigVP8)) { 471 return ENCODE_INVALID_PARAMS; 472 } 473 474 mVideoConfigVP8 = *encConfigVP8; 475 } 476 break; 477 478 case VideoConfigTypeVP8ReferenceFrame:{ 479 VideoConfigVP8ReferenceFrame *encConfigVP8ReferenceFrame = 480 reinterpret_cast<VideoConfigVP8ReferenceFrame*> (videoEncConfig); 481 482 if (encConfigVP8ReferenceFrame->size != sizeof(VideoConfigVP8ReferenceFrame)) { 483 return ENCODE_INVALID_PARAMS; 484 } 485 486 mVideoConfigVP8ReferenceFrame = *encConfigVP8ReferenceFrame; 487 488 } 489 break; 490 491 case VideoConfigTypeVP8MaxFrameSizeRatio:{ 492 VideoConfigVP8MaxFrameSizeRatio *encConfigVP8MaxFrameSizeRatio = 493 reinterpret_cast<VideoConfigVP8MaxFrameSizeRatio*> (videoEncConfig); 494 495 if (encConfigVP8MaxFrameSizeRatio->size != sizeof(VideoConfigVP8MaxFrameSizeRatio)) { 496 return ENCODE_INVALID_PARAMS; 497 } 498 499 mVideoParamsVP8.max_frame_size_ratio = encConfigVP8MaxFrameSizeRatio->max_frame_size_ratio; 500 mRenderMaxFrameSize = true; 501 } 502 break; 503 504 case VideoConfigTypeIDRRequest:{ 505 mVideoConfigVP8.force_kf = 1; 506 mForceKFrame = true; 507 } 508 break; 509 510 default: { 511 LOG_E ("Invalid Config Type"); 512 break; 513 } 514 } 515 return ENCODE_SUCCESS; 516 } 517