1 /************************************************************************** 2 * 3 * Copyright 2013 Advanced Micro Devices, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Christian Knig <christian.koenig (at) amd.com> 31 * 32 */ 33 34 35 #include <assert.h> 36 37 #include <OMX_Video.h> 38 39 /* bellagio defines a DEBUG macro that we don't want */ 40 #ifndef DEBUG 41 #include <bellagio/omxcore.h> 42 #undef DEBUG 43 #else 44 #include <bellagio/omxcore.h> 45 #endif 46 47 #include <bellagio/omx_base_video_port.h> 48 49 #include "pipe/p_screen.h" 50 #include "pipe/p_video_codec.h" 51 #include "state_tracker/drm_driver.h" 52 #include "util/u_memory.h" 53 #include "vl/vl_video_buffer.h" 54 55 #include "entrypoint.h" 56 #include "vid_enc.h" 57 58 struct encode_task { 59 struct list_head list; 60 61 struct pipe_video_buffer *buf; 62 unsigned pic_order_cnt; 63 struct pipe_resource *bitstream; 64 void *feedback; 65 }; 66 67 struct input_buf_private { 68 struct list_head tasks; 69 70 struct pipe_resource *resource; 71 struct pipe_transfer *transfer; 72 }; 73 74 struct output_buf_private { 75 struct pipe_resource *bitstream; 76 struct pipe_transfer *transfer; 77 }; 78 79 static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); 80 static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp); 81 static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); 82 static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); 83 static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); 84 static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); 85 static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); 86 static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, 87 OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); 88 static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, 89 OMX_PTR private, OMX_U32 size, OMX_U8 *mem); 90 static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); 91 static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); 92 static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, 93 OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); 94 static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); 95 static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); 96 97 static void enc_ReleaseTasks(struct list_head *head); 98 99 OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp) 100 { 101 comp->componentVersion.s.nVersionMajor = 0; 102 comp->componentVersion.s.nVersionMinor = 0; 103 comp->componentVersion.s.nRevision = 0; 104 comp->componentVersion.s.nStep = 1; 105 comp->name_specific_length = 1; 106 comp->constructor = vid_enc_Constructor; 107 108 comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); 109 if (!comp->name) 110 return OMX_ErrorInsufficientResources; 111 112 comp->name_specific = CALLOC(1, sizeof(char *)); 113 if (!comp->name_specific) 114 goto error_arrays; 115 116 comp->role_specific = CALLOC(1, sizeof(char *)); 117 if (!comp->role_specific) 118 goto error_arrays; 119 120 comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); 121 if (comp->name_specific[0] == NULL) 122 goto error_specific; 123 124 comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); 125 if (comp->role_specific[0] == NULL) 126 goto error_specific; 127 128 strcpy(comp->name, OMX_VID_ENC_BASE_NAME); 129 strcpy(comp->name_specific[0], OMX_VID_ENC_AVC_NAME); 130 strcpy(comp->role_specific[0], OMX_VID_ENC_AVC_ROLE); 131 132 return OMX_ErrorNone; 133 134 error_specific: 135 FREE(comp->role_specific[0]); 136 FREE(comp->name_specific[0]); 137 138 error_arrays: 139 FREE(comp->role_specific); 140 FREE(comp->name_specific); 141 142 FREE(comp->name); 143 144 return OMX_ErrorInsufficientResources; 145 } 146 147 static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) 148 { 149 vid_enc_PrivateType *priv; 150 omx_base_video_PortType *port; 151 struct pipe_screen *screen; 152 OMX_ERRORTYPE r; 153 int i; 154 155 assert(!comp->pComponentPrivate); 156 157 priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_enc_PrivateType)); 158 if (!priv) 159 return OMX_ErrorInsufficientResources; 160 161 r = omx_base_filter_Constructor(comp, name); 162 if (r) 163 return r; 164 165 priv->BufferMgmtCallback = vid_enc_BufferEncoded; 166 priv->messageHandler = vid_enc_MessageHandler; 167 priv->destructor = vid_enc_Destructor; 168 169 comp->SetParameter = vid_enc_SetParameter; 170 comp->GetParameter = vid_enc_GetParameter; 171 comp->GetConfig = vid_enc_GetConfig; 172 comp->SetConfig = vid_enc_SetConfig; 173 174 priv->screen = omx_get_screen(); 175 if (!priv->screen) 176 return OMX_ErrorInsufficientResources; 177 178 screen = priv->screen->pscreen; 179 if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, 180 PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) 181 return OMX_ErrorBadParameter; 182 183 priv->s_pipe = screen->context_create(screen, priv->screen, 0); 184 if (!priv->s_pipe) 185 return OMX_ErrorInsufficientResources; 186 187 if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { 188 priv->s_pipe->destroy(priv->s_pipe); 189 priv->s_pipe = NULL; 190 return OMX_ErrorInsufficientResources; 191 } 192 193 if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { 194 vl_compositor_cleanup(&priv->compositor); 195 priv->s_pipe->destroy(priv->s_pipe); 196 priv->s_pipe = NULL; 197 return OMX_ErrorInsufficientResources; 198 } 199 200 priv->t_pipe = screen->context_create(screen, priv->screen, 0); 201 if (!priv->t_pipe) 202 return OMX_ErrorInsufficientResources; 203 204 priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; 205 priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; 206 priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); 207 if (!priv->ports) 208 return OMX_ErrorInsufficientResources; 209 210 for (i = 0; i < 2; ++i) { 211 priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); 212 if (!priv->ports[i]) 213 return OMX_ErrorInsufficientResources; 214 215 base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); 216 } 217 218 port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; 219 port->sPortParam.format.video.nFrameWidth = 176; 220 port->sPortParam.format.video.nFrameHeight = 144; 221 port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 222 port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 223 port->sPortParam.nBufferCountActual = 8; 224 port->sPortParam.nBufferCountMin = 4; 225 226 port->Port_SendBufferFunction = vid_enc_EncodeFrame; 227 port->Port_AllocateBuffer = vid_enc_AllocateInBuffer; 228 port->Port_UseBuffer = vid_enc_UseInBuffer; 229 port->Port_FreeBuffer = vid_enc_FreeInBuffer; 230 231 port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; 232 strcpy(port->sPortParam.format.video.cMIMEType,"video/H264"); 233 port->sPortParam.format.video.nFrameWidth = 176; 234 port->sPortParam.format.video.nFrameHeight = 144; 235 port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 236 port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingAVC; 237 238 port->Port_AllocateBuffer = vid_enc_AllocateOutBuffer; 239 port->Port_FreeBuffer = vid_enc_FreeOutBuffer; 240 241 priv->bitrate.eControlRate = OMX_Video_ControlRateDisable; 242 priv->bitrate.nTargetBitrate = 0; 243 244 priv->quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; 245 priv->quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; 246 priv->quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; 247 248 priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; 249 priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; 250 251 priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; 252 priv->frame_num = 0; 253 priv->pic_order_cnt = 0; 254 priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); 255 256 priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; 257 priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; 258 259 LIST_INITHEAD(&priv->free_tasks); 260 LIST_INITHEAD(&priv->used_tasks); 261 LIST_INITHEAD(&priv->b_frames); 262 LIST_INITHEAD(&priv->stacked_tasks); 263 264 return OMX_ErrorNone; 265 } 266 267 static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp) 268 { 269 vid_enc_PrivateType* priv = comp->pComponentPrivate; 270 int i; 271 272 enc_ReleaseTasks(&priv->free_tasks); 273 enc_ReleaseTasks(&priv->used_tasks); 274 enc_ReleaseTasks(&priv->b_frames); 275 enc_ReleaseTasks(&priv->stacked_tasks); 276 277 if (priv->ports) { 278 for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { 279 if(priv->ports[i]) 280 priv->ports[i]->PortDestructor(priv->ports[i]); 281 } 282 FREE(priv->ports); 283 priv->ports=NULL; 284 } 285 286 for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) 287 if (priv->scale_buffer[i]) 288 priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); 289 290 if (priv->s_pipe) { 291 vl_compositor_cleanup_state(&priv->cstate); 292 vl_compositor_cleanup(&priv->compositor); 293 priv->s_pipe->destroy(priv->s_pipe); 294 } 295 296 if (priv->t_pipe) 297 priv->t_pipe->destroy(priv->t_pipe); 298 299 if (priv->screen) 300 omx_put_screen(); 301 302 return omx_workaround_Destructor(comp); 303 } 304 305 static OMX_ERRORTYPE enc_AllocateBackTexture(omx_base_PortType *port, 306 struct pipe_resource **resource, 307 struct pipe_transfer **transfer, 308 OMX_U8 **map) 309 { 310 OMX_COMPONENTTYPE* comp = port->standCompContainer; 311 vid_enc_PrivateType *priv = comp->pComponentPrivate; 312 struct pipe_resource buf_templ; 313 struct pipe_box box = {}; 314 OMX_U8 *ptr; 315 316 memset(&buf_templ, 0, sizeof buf_templ); 317 buf_templ.target = PIPE_TEXTURE_2D; 318 buf_templ.format = PIPE_FORMAT_I8_UNORM; 319 buf_templ.bind = PIPE_BIND_LINEAR; 320 buf_templ.usage = PIPE_USAGE_STAGING; 321 buf_templ.flags = 0; 322 buf_templ.width0 = port->sPortParam.format.video.nFrameWidth; 323 buf_templ.height0 = port->sPortParam.format.video.nFrameHeight * 3 / 2; 324 buf_templ.depth0 = 1; 325 buf_templ.array_size = 1; 326 327 *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); 328 if (!*resource) 329 return OMX_ErrorInsufficientResources; 330 331 box.width = (*resource)->width0; 332 box.height = (*resource)->height0; 333 box.depth = (*resource)->depth0; 334 ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); 335 if (map) 336 *map = ptr; 337 338 return OMX_ErrorNone; 339 } 340 341 static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) 342 { 343 OMX_COMPONENTTYPE *comp = handle; 344 vid_enc_PrivateType *priv = comp->pComponentPrivate; 345 OMX_ERRORTYPE r; 346 347 if (!param) 348 return OMX_ErrorBadParameter; 349 350 switch(idx) { 351 case OMX_IndexParamPortDefinition: { 352 OMX_PARAM_PORTDEFINITIONTYPE *def = param; 353 354 r = omx_base_component_SetParameter(handle, idx, param); 355 if (r) 356 return r; 357 358 if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { 359 omx_base_video_PortType *port; 360 unsigned framesize; 361 struct pipe_resource *resource; 362 struct pipe_transfer *transfer; 363 364 port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; 365 enc_AllocateBackTexture(priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX], 366 &resource, &transfer, NULL); 367 port->sPortParam.format.video.nStride = transfer->stride; 368 pipe_transfer_unmap(priv->s_pipe, transfer); 369 pipe_resource_reference(&resource, NULL); 370 371 framesize = port->sPortParam.format.video.nStride * 372 port->sPortParam.format.video.nFrameHeight; 373 port->sPortParam.format.video.nSliceHeight = port->sPortParam.format.video.nFrameHeight; 374 port->sPortParam.nBufferSize = framesize * 3 / 2; 375 376 port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; 377 port->sPortParam.nBufferSize = framesize * 512 / (16*16); 378 379 priv->frame_rate = def->format.video.xFramerate; 380 381 priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, 382 OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); 383 } 384 break; 385 } 386 case OMX_IndexParamStandardComponentRole: { 387 OMX_PARAM_COMPONENTROLETYPE *role = param; 388 389 r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); 390 if (r) 391 return r; 392 393 if (strcmp((char *)role->cRole, OMX_VID_ENC_AVC_ROLE)) { 394 return OMX_ErrorBadParameter; 395 } 396 397 break; 398 } 399 case OMX_IndexParamVideoBitrate: { 400 OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; 401 402 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); 403 if (r) 404 return r; 405 406 priv->bitrate = *bitrate; 407 408 break; 409 } 410 case OMX_IndexParamVideoQuantization: { 411 OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; 412 413 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); 414 if (r) 415 return r; 416 417 priv->quant = *quant; 418 419 break; 420 } 421 case OMX_IndexParamVideoProfileLevelCurrent: { 422 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; 423 424 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); 425 if (r) 426 return r; 427 428 priv->profile_level = *profile_level; 429 430 break; 431 } 432 default: 433 return omx_base_component_SetParameter(handle, idx, param); 434 } 435 return OMX_ErrorNone; 436 } 437 438 static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) 439 { 440 OMX_COMPONENTTYPE *comp = handle; 441 vid_enc_PrivateType *priv = comp->pComponentPrivate; 442 OMX_ERRORTYPE r; 443 444 if (!param) 445 return OMX_ErrorBadParameter; 446 447 switch(idx) { 448 case OMX_IndexParamStandardComponentRole: { 449 OMX_PARAM_COMPONENTROLETYPE *role = param; 450 451 r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); 452 if (r) 453 return r; 454 455 strcpy((char *)role->cRole, OMX_VID_ENC_AVC_ROLE); 456 break; 457 } 458 case OMX_IndexParamVideoInit: 459 r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); 460 if (r) 461 return r; 462 463 memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); 464 break; 465 466 case OMX_IndexParamVideoPortFormat: { 467 OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; 468 omx_base_video_PortType *port; 469 470 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 471 if (r) 472 return r; 473 474 if (format->nPortIndex > 1) 475 return OMX_ErrorBadPortIndex; 476 477 port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; 478 memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 479 break; 480 } 481 case OMX_IndexParamVideoBitrate: { 482 OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; 483 484 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); 485 if (r) 486 return r; 487 488 bitrate->eControlRate = priv->bitrate.eControlRate; 489 bitrate->nTargetBitrate = priv->bitrate.nTargetBitrate; 490 491 break; 492 } 493 case OMX_IndexParamVideoQuantization: { 494 OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; 495 496 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); 497 if (r) 498 return r; 499 500 quant->nQpI = priv->quant.nQpI; 501 quant->nQpP = priv->quant.nQpP; 502 quant->nQpB = priv->quant.nQpB; 503 504 break; 505 } 506 case OMX_IndexParamVideoProfileLevelCurrent: { 507 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; 508 509 r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); 510 if (r) 511 return r; 512 513 profile_level->eProfile = priv->profile_level.eProfile; 514 profile_level->eLevel = priv->profile_level.eLevel; 515 516 break; 517 } 518 default: 519 return omx_base_component_GetParameter(handle, idx, param); 520 } 521 return OMX_ErrorNone; 522 } 523 524 static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) 525 { 526 OMX_COMPONENTTYPE *comp = handle; 527 vid_enc_PrivateType *priv = comp->pComponentPrivate; 528 OMX_ERRORTYPE r; 529 int i; 530 531 if (!config) 532 return OMX_ErrorBadParameter; 533 534 switch(idx) { 535 case OMX_IndexConfigVideoIntraVOPRefresh: { 536 OMX_CONFIG_INTRAREFRESHVOPTYPE *type = config; 537 538 r = checkHeader(config, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); 539 if (r) 540 return r; 541 542 priv->force_pic_type = *type; 543 544 break; 545 } 546 case OMX_IndexConfigCommonScale: { 547 OMX_CONFIG_SCALEFACTORTYPE *scale = config; 548 549 r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); 550 if (r) 551 return r; 552 553 if (scale->xWidth < 176 || scale->xHeight < 144) 554 return OMX_ErrorBadParameter; 555 556 for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { 557 if (priv->scale_buffer[i]) { 558 priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); 559 priv->scale_buffer[i] = NULL; 560 } 561 } 562 563 priv->scale = *scale; 564 if (priv->scale.xWidth != 0xffffffff && priv->scale.xHeight != 0xffffffff) { 565 struct pipe_video_buffer templat = {}; 566 567 templat.buffer_format = PIPE_FORMAT_NV12; 568 templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 569 templat.width = priv->scale.xWidth; 570 templat.height = priv->scale.xHeight; 571 templat.interlaced = false; 572 for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { 573 priv->scale_buffer[i] = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); 574 if (!priv->scale_buffer[i]) 575 return OMX_ErrorInsufficientResources; 576 } 577 } 578 579 break; 580 } 581 default: 582 return omx_base_component_SetConfig(handle, idx, config); 583 } 584 585 return OMX_ErrorNone; 586 } 587 588 static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) 589 { 590 OMX_COMPONENTTYPE *comp = handle; 591 vid_enc_PrivateType *priv = comp->pComponentPrivate; 592 OMX_ERRORTYPE r; 593 594 if (!config) 595 return OMX_ErrorBadParameter; 596 597 switch(idx) { 598 case OMX_IndexConfigCommonScale: { 599 OMX_CONFIG_SCALEFACTORTYPE *scale = config; 600 601 r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); 602 if (r) 603 return r; 604 605 scale->xWidth = priv->scale.xWidth; 606 scale->xHeight = priv->scale.xHeight; 607 608 break; 609 } 610 default: 611 return omx_base_component_GetConfig(handle, idx, config); 612 } 613 614 return OMX_ErrorNone; 615 } 616 617 static enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) 618 { 619 switch (omx_profile) { 620 case OMX_VIDEO_AVCProfileBaseline: 621 return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; 622 case OMX_VIDEO_AVCProfileMain: 623 return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; 624 case OMX_VIDEO_AVCProfileExtended: 625 return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; 626 case OMX_VIDEO_AVCProfileHigh: 627 return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; 628 case OMX_VIDEO_AVCProfileHigh10: 629 return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; 630 case OMX_VIDEO_AVCProfileHigh422: 631 return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; 632 case OMX_VIDEO_AVCProfileHigh444: 633 return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; 634 default: 635 return PIPE_VIDEO_PROFILE_UNKNOWN; 636 } 637 } 638 639 static unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) 640 { 641 switch (omx_level) { 642 case OMX_VIDEO_AVCLevel1: 643 case OMX_VIDEO_AVCLevel1b: 644 return 10; 645 case OMX_VIDEO_AVCLevel11: 646 return 11; 647 case OMX_VIDEO_AVCLevel12: 648 return 12; 649 case OMX_VIDEO_AVCLevel13: 650 return 13; 651 case OMX_VIDEO_AVCLevel2: 652 return 20; 653 case OMX_VIDEO_AVCLevel21: 654 return 21; 655 case OMX_VIDEO_AVCLevel22: 656 return 22; 657 case OMX_VIDEO_AVCLevel3: 658 return 30; 659 case OMX_VIDEO_AVCLevel31: 660 return 31; 661 case OMX_VIDEO_AVCLevel32: 662 return 32; 663 case OMX_VIDEO_AVCLevel4: 664 return 40; 665 case OMX_VIDEO_AVCLevel41: 666 return 41; 667 default: 668 case OMX_VIDEO_AVCLevel42: 669 return 42; 670 case OMX_VIDEO_AVCLevel5: 671 return 50; 672 case OMX_VIDEO_AVCLevel51: 673 return 51; 674 } 675 } 676 677 static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) 678 { 679 vid_enc_PrivateType* priv = comp->pComponentPrivate; 680 681 if (msg->messageType == OMX_CommandStateSet) { 682 if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { 683 684 struct pipe_video_codec templat = {}; 685 omx_base_video_PortType *port; 686 687 port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; 688 689 templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); 690 templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); 691 templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; 692 templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 693 templat.width = priv->scale_buffer[priv->current_scale_buffer] ? 694 priv->scale.xWidth : port->sPortParam.format.video.nFrameWidth; 695 templat.height = priv->scale_buffer[priv->current_scale_buffer] ? 696 priv->scale.xHeight : port->sPortParam.format.video.nFrameHeight; 697 698 if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { 699 struct pipe_screen *screen = priv->screen->pscreen; 700 templat.max_references = 1; 701 priv->stacked_frames_num = 702 screen->get_video_param(screen, 703 PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, 704 PIPE_VIDEO_ENTRYPOINT_ENCODE, 705 PIPE_VIDEO_CAP_STACKED_FRAMES); 706 } else { 707 templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; 708 priv->stacked_frames_num = 1; 709 } 710 priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); 711 712 } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { 713 if (priv->codec) { 714 priv->codec->destroy(priv->codec); 715 priv->codec = NULL; 716 } 717 } 718 } 719 720 return omx_base_component_MessageHandler(comp, msg); 721 } 722 723 static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, 724 OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) 725 { 726 struct input_buf_private *inp; 727 OMX_ERRORTYPE r; 728 729 r = base_port_AllocateBuffer(port, buf, idx, private, size); 730 if (r) 731 return r; 732 733 inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); 734 if (!inp) { 735 base_port_FreeBuffer(port, idx, *buf); 736 return OMX_ErrorInsufficientResources; 737 } 738 739 LIST_INITHEAD(&inp->tasks); 740 741 FREE((*buf)->pBuffer); 742 r = enc_AllocateBackTexture(port, &inp->resource, &inp->transfer, &(*buf)->pBuffer); 743 if (r) { 744 FREE(inp); 745 base_port_FreeBuffer(port, idx, *buf); 746 return r; 747 } 748 749 return OMX_ErrorNone; 750 } 751 752 static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, 753 OMX_PTR private, OMX_U32 size, OMX_U8 *mem) 754 { 755 struct input_buf_private *inp; 756 OMX_ERRORTYPE r; 757 758 r = base_port_UseBuffer(port, buf, idx, private, size, mem); 759 if (r) 760 return r; 761 762 inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); 763 if (!inp) { 764 base_port_FreeBuffer(port, idx, *buf); 765 return OMX_ErrorInsufficientResources; 766 } 767 768 LIST_INITHEAD(&inp->tasks); 769 770 return OMX_ErrorNone; 771 } 772 773 static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) 774 { 775 OMX_COMPONENTTYPE* comp = port->standCompContainer; 776 vid_enc_PrivateType *priv = comp->pComponentPrivate; 777 struct input_buf_private *inp = buf->pInputPortPrivate; 778 779 if (inp) { 780 enc_ReleaseTasks(&inp->tasks); 781 if (inp->transfer) 782 pipe_transfer_unmap(priv->s_pipe, inp->transfer); 783 pipe_resource_reference(&inp->resource, NULL); 784 FREE(inp); 785 } 786 buf->pBuffer = NULL; 787 788 return base_port_FreeBuffer(port, idx, buf); 789 } 790 791 static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, 792 OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) 793 { 794 OMX_ERRORTYPE r; 795 796 r = base_port_AllocateBuffer(port, buf, idx, private, size); 797 if (r) 798 return r; 799 800 FREE((*buf)->pBuffer); 801 (*buf)->pBuffer = NULL; 802 (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); 803 if (!(*buf)->pOutputPortPrivate) { 804 base_port_FreeBuffer(port, idx, *buf); 805 return OMX_ErrorInsufficientResources; 806 } 807 808 return OMX_ErrorNone; 809 } 810 811 static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) 812 { 813 OMX_COMPONENTTYPE* comp = port->standCompContainer; 814 vid_enc_PrivateType *priv = comp->pComponentPrivate; 815 816 if (buf->pOutputPortPrivate) { 817 struct output_buf_private *outp = buf->pOutputPortPrivate; 818 if (outp->transfer) 819 pipe_transfer_unmap(priv->t_pipe, outp->transfer); 820 pipe_resource_reference(&outp->bitstream, NULL); 821 FREE(outp); 822 buf->pOutputPortPrivate = NULL; 823 } 824 buf->pBuffer = NULL; 825 826 return base_port_FreeBuffer(port, idx, buf); 827 } 828 829 static struct encode_task *enc_NeedTask(omx_base_PortType *port) 830 { 831 OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; 832 OMX_COMPONENTTYPE* comp = port->standCompContainer; 833 vid_enc_PrivateType *priv = comp->pComponentPrivate; 834 835 struct pipe_video_buffer templat = {}; 836 struct encode_task *task; 837 838 if (!LIST_IS_EMPTY(&priv->free_tasks)) { 839 task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); 840 LIST_DEL(&task->list); 841 return task; 842 } 843 844 /* allocate a new one */ 845 task = CALLOC_STRUCT(encode_task); 846 if (!task) 847 return NULL; 848 849 templat.buffer_format = PIPE_FORMAT_NV12; 850 templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 851 templat.width = def->nFrameWidth; 852 templat.height = def->nFrameHeight; 853 templat.interlaced = false; 854 855 task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); 856 if (!task->buf) { 857 FREE(task); 858 return NULL; 859 } 860 861 return task; 862 } 863 864 static void enc_MoveTasks(struct list_head *from, struct list_head *to) 865 { 866 to->prev->next = from->next; 867 from->next->prev = to->prev; 868 from->prev->next = to; 869 to->prev = from->prev; 870 LIST_INITHEAD(from); 871 } 872 873 static void enc_ReleaseTasks(struct list_head *head) 874 { 875 struct encode_task *i, *next; 876 877 if (!head || !head->next) 878 return; 879 880 LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { 881 pipe_resource_reference(&i->bitstream, NULL); 882 i->buf->destroy(i->buf); 883 FREE(i); 884 } 885 } 886 887 static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf, 888 struct pipe_video_buffer *vbuf) 889 { 890 OMX_COMPONENTTYPE* comp = port->standCompContainer; 891 vid_enc_PrivateType *priv = comp->pComponentPrivate; 892 OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; 893 struct pipe_box box = {}; 894 struct input_buf_private *inp = buf->pInputPortPrivate; 895 896 if (!inp->resource) { 897 struct pipe_sampler_view **views; 898 void *ptr; 899 900 views = vbuf->get_sampler_view_planes(vbuf); 901 if (!views) 902 return OMX_ErrorInsufficientResources; 903 904 ptr = buf->pBuffer; 905 box.width = def->nFrameWidth; 906 box.height = def->nFrameHeight; 907 box.depth = 1; 908 priv->s_pipe->texture_subdata(priv->s_pipe, views[0]->texture, 0, 909 PIPE_TRANSFER_WRITE, &box, 910 ptr, def->nStride, 0); 911 ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); 912 box.width = def->nFrameWidth / 2; 913 box.height = def->nFrameHeight / 2; 914 box.depth = 1; 915 priv->s_pipe->texture_subdata(priv->s_pipe, views[1]->texture, 0, 916 PIPE_TRANSFER_WRITE, &box, 917 ptr, def->nStride, 0); 918 } else { 919 struct pipe_blit_info blit; 920 struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; 921 922 pipe_transfer_unmap(priv->s_pipe, inp->transfer); 923 924 box.width = def->nFrameWidth; 925 box.height = def->nFrameHeight; 926 box.depth = 1; 927 928 priv->s_pipe->resource_copy_region(priv->s_pipe, 929 dst_buf->resources[0], 930 0, 0, 0, 0, inp->resource, 0, &box); 931 932 memset(&blit, 0, sizeof(blit)); 933 blit.src.resource = inp->resource; 934 blit.src.format = inp->resource->format; 935 936 blit.src.box.x = 0; 937 blit.src.box.y = def->nFrameHeight; 938 blit.src.box.width = def->nFrameWidth; 939 blit.src.box.height = def->nFrameHeight / 2 ; 940 blit.src.box.depth = 1; 941 942 blit.dst.resource = dst_buf->resources[1]; 943 blit.dst.format = blit.dst.resource->format; 944 945 blit.dst.box.width = def->nFrameWidth / 2; 946 blit.dst.box.height = def->nFrameHeight / 2; 947 blit.dst.box.depth = 1; 948 blit.filter = PIPE_TEX_FILTER_NEAREST; 949 950 blit.mask = PIPE_MASK_G; 951 priv->s_pipe->blit(priv->s_pipe, &blit); 952 953 blit.src.box.x = 1; 954 blit.mask = PIPE_MASK_R; 955 priv->s_pipe->blit(priv->s_pipe, &blit); 956 priv->s_pipe->flush(priv->s_pipe, NULL, 0); 957 958 box.width = inp->resource->width0; 959 box.height = inp->resource->height0; 960 box.depth = inp->resource->depth0; 961 buf->pBuffer = priv->s_pipe->transfer_map(priv->s_pipe, inp->resource, 0, 962 PIPE_TRANSFER_WRITE, &box, 963 &inp->transfer); 964 } 965 966 return OMX_ErrorNone; 967 } 968 969 static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size) 970 { 971 OMX_COMPONENTTYPE* comp = port->standCompContainer; 972 vid_enc_PrivateType *priv = comp->pComponentPrivate; 973 OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; 974 struct pipe_video_buffer *src_buf = *vbuf; 975 struct vl_compositor *compositor = &priv->compositor; 976 struct vl_compositor_state *s = &priv->cstate; 977 struct pipe_sampler_view **views; 978 struct pipe_surface **dst_surface; 979 unsigned i; 980 981 if (!priv->scale_buffer[priv->current_scale_buffer]) 982 return; 983 984 views = src_buf->get_sampler_view_planes(src_buf); 985 dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces 986 (priv->scale_buffer[priv->current_scale_buffer]); 987 vl_compositor_clear_layers(s); 988 989 for (i = 0; i < VL_MAX_SURFACES; ++i) { 990 struct u_rect src_rect; 991 if (!views[i] || !dst_surface[i]) 992 continue; 993 src_rect.x0 = 0; 994 src_rect.y0 = 0; 995 src_rect.x1 = def->nFrameWidth; 996 src_rect.y1 = def->nFrameHeight; 997 if (i > 0) { 998 src_rect.x1 /= 2; 999 src_rect.y1 /= 2; 1000 } 1001 vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); 1002 vl_compositor_render(s, compositor, dst_surface[i], NULL, false); 1003 } 1004 *size = priv->scale.xWidth * priv->scale.xHeight * 2; 1005 *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; 1006 priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; 1007 } 1008 1009 static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) 1010 { 1011 picture->motion_est.enc_disable_sub_mode = 0x000000fe; 1012 picture->motion_est.enc_ime2_search_range_x = 0x00000001; 1013 picture->motion_est.enc_ime2_search_range_y = 0x00000001; 1014 picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; 1015 } 1016 1017 static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture) 1018 { 1019 OMX_COMPONENTTYPE* comp = port->standCompContainer; 1020 vid_enc_PrivateType *priv = comp->pComponentPrivate; 1021 struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; 1022 1023 switch (priv->bitrate.eControlRate) { 1024 case OMX_Video_ControlRateVariable: 1025 rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; 1026 break; 1027 case OMX_Video_ControlRateConstant: 1028 rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; 1029 break; 1030 case OMX_Video_ControlRateVariableSkipFrames: 1031 rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; 1032 break; 1033 case OMX_Video_ControlRateConstantSkipFrames: 1034 rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; 1035 break; 1036 default: 1037 rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; 1038 break; 1039 } 1040 1041 rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; 1042 rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; 1043 1044 if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { 1045 if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) 1046 rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; 1047 else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) 1048 rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; 1049 else 1050 rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; 1051 rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; 1052 if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) 1053 rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); 1054 else 1055 rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; 1056 1057 if (rate_ctrl->frame_rate_num) { 1058 unsigned long long t = rate_ctrl->target_bitrate; 1059 t *= rate_ctrl->frame_rate_den; 1060 rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; 1061 } else { 1062 rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; 1063 } 1064 rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; 1065 rate_ctrl->peak_bits_picture_fraction = 0; 1066 } 1067 1068 picture->quant_i_frames = priv->quant.nQpI; 1069 picture->quant_p_frames = priv->quant.nQpP; 1070 picture->quant_b_frames = priv->quant.nQpB; 1071 1072 picture->frame_num = priv->frame_num; 1073 picture->ref_idx_l0 = priv->ref_idx_l0; 1074 picture->ref_idx_l1 = priv->ref_idx_l1; 1075 picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); 1076 enc_GetPictureParamPreset(picture); 1077 } 1078 1079 static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task, 1080 enum pipe_h264_enc_picture_type picture_type) 1081 { 1082 OMX_COMPONENTTYPE* comp = port->standCompContainer; 1083 vid_enc_PrivateType *priv = comp->pComponentPrivate; 1084 unsigned size = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize; 1085 struct pipe_video_buffer *vbuf = task->buf; 1086 struct pipe_h264_enc_picture_desc picture = {}; 1087 1088 /* -------------- scale input image --------- */ 1089 enc_ScaleInput(port, &vbuf, &size); 1090 priv->s_pipe->flush(priv->s_pipe, NULL, 0); 1091 1092 /* -------------- allocate output buffer --------- */ 1093 task->bitstream = pipe_buffer_create(priv->s_pipe->screen, PIPE_BIND_VERTEX_BUFFER, 1094 PIPE_USAGE_STREAM, size); 1095 1096 picture.picture_type = picture_type; 1097 picture.pic_order_cnt = task->pic_order_cnt; 1098 if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) 1099 picture.not_referenced = true; 1100 enc_ControlPicture(port, &picture); 1101 1102 /* -------------- encode frame --------- */ 1103 priv->codec->begin_frame(priv->codec, vbuf, &picture.base); 1104 priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); 1105 priv->codec->end_frame(priv->codec, vbuf, &picture.base); 1106 } 1107 1108 static void enc_ClearBframes(omx_base_PortType *port, struct input_buf_private *inp) 1109 { 1110 OMX_COMPONENTTYPE* comp = port->standCompContainer; 1111 vid_enc_PrivateType *priv = comp->pComponentPrivate; 1112 struct encode_task *task; 1113 1114 if (LIST_IS_EMPTY(&priv->b_frames)) 1115 return; 1116 1117 task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); 1118 LIST_DEL(&task->list); 1119 1120 /* promote last from to P frame */ 1121 priv->ref_idx_l0 = priv->ref_idx_l1; 1122 enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_P); 1123 LIST_ADDTAIL(&task->list, &inp->tasks); 1124 priv->ref_idx_l1 = priv->frame_num++; 1125 1126 /* handle B frames */ 1127 LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { 1128 enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); 1129 if (!priv->restricted_b_frames) 1130 priv->ref_idx_l0 = priv->frame_num; 1131 priv->frame_num++; 1132 } 1133 1134 enc_MoveTasks(&priv->b_frames, &inp->tasks); 1135 } 1136 1137 static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) 1138 { 1139 OMX_COMPONENTTYPE* comp = port->standCompContainer; 1140 vid_enc_PrivateType *priv = comp->pComponentPrivate; 1141 struct input_buf_private *inp = buf->pInputPortPrivate; 1142 enum pipe_h264_enc_picture_type picture_type; 1143 struct encode_task *task; 1144 unsigned stacked_num = 0; 1145 OMX_ERRORTYPE err; 1146 1147 enc_MoveTasks(&inp->tasks, &priv->free_tasks); 1148 task = enc_NeedTask(port); 1149 if (!task) 1150 return OMX_ErrorInsufficientResources; 1151 1152 if (buf->nFilledLen == 0) { 1153 if (buf->nFlags & OMX_BUFFERFLAG_EOS) { 1154 buf->nFilledLen = buf->nAllocLen; 1155 enc_ClearBframes(port, inp); 1156 enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); 1157 priv->codec->flush(priv->codec); 1158 } 1159 return base_port_SendBufferFunction(port, buf); 1160 } 1161 1162 if (buf->pOutputPortPrivate) { 1163 struct pipe_video_buffer *vbuf = buf->pOutputPortPrivate; 1164 buf->pOutputPortPrivate = task->buf; 1165 task->buf = vbuf; 1166 } else { 1167 /* ------- load input image into video buffer ---- */ 1168 err = enc_LoadImage(port, buf, task->buf); 1169 if (err != OMX_ErrorNone) { 1170 FREE(task); 1171 return err; 1172 } 1173 } 1174 1175 /* -------------- determine picture type --------- */ 1176 if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || 1177 priv->force_pic_type.IntraRefreshVOP) { 1178 enc_ClearBframes(port, inp); 1179 picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; 1180 priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; 1181 priv->frame_num = 0; 1182 } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || 1183 !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || 1184 (buf->nFlags & OMX_BUFFERFLAG_EOS)) { 1185 picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; 1186 } else { 1187 picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; 1188 } 1189 1190 task->pic_order_cnt = priv->pic_order_cnt++; 1191 1192 if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { 1193 /* put frame at the tail of the queue */ 1194 LIST_ADDTAIL(&task->list, &priv->b_frames); 1195 } else { 1196 /* handle I or P frame */ 1197 priv->ref_idx_l0 = priv->ref_idx_l1; 1198 enc_HandleTask(port, task, picture_type); 1199 LIST_ADDTAIL(&task->list, &priv->stacked_tasks); 1200 LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { 1201 ++stacked_num; 1202 } 1203 if (stacked_num == priv->stacked_frames_num) { 1204 struct encode_task *t; 1205 t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); 1206 LIST_DEL(&t->list); 1207 LIST_ADDTAIL(&t->list, &inp->tasks); 1208 } 1209 priv->ref_idx_l1 = priv->frame_num++; 1210 1211 /* handle B frames */ 1212 LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { 1213 enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); 1214 if (!priv->restricted_b_frames) 1215 priv->ref_idx_l0 = priv->frame_num; 1216 priv->frame_num++; 1217 } 1218 1219 enc_MoveTasks(&priv->b_frames, &inp->tasks); 1220 } 1221 1222 if (LIST_IS_EMPTY(&inp->tasks)) 1223 return port->ReturnBufferFunction(port, buf); 1224 else 1225 return base_port_SendBufferFunction(port, buf); 1226 } 1227 1228 static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) 1229 { 1230 vid_enc_PrivateType *priv = comp->pComponentPrivate; 1231 struct output_buf_private *outp = output->pOutputPortPrivate; 1232 struct input_buf_private *inp = input->pInputPortPrivate; 1233 struct encode_task *task; 1234 struct pipe_box box = {}; 1235 unsigned size; 1236 1237 if (!inp || LIST_IS_EMPTY(&inp->tasks)) { 1238 input->nFilledLen = 0; /* mark buffer as empty */ 1239 enc_MoveTasks(&priv->used_tasks, &inp->tasks); 1240 return; 1241 } 1242 1243 task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); 1244 LIST_DEL(&task->list); 1245 LIST_ADDTAIL(&task->list, &priv->used_tasks); 1246 1247 if (!task->bitstream) 1248 return; 1249 1250 /* ------------- map result buffer ----------------- */ 1251 1252 if (outp->transfer) 1253 pipe_transfer_unmap(priv->t_pipe, outp->transfer); 1254 1255 pipe_resource_reference(&outp->bitstream, task->bitstream); 1256 pipe_resource_reference(&task->bitstream, NULL); 1257 1258 box.width = outp->bitstream->width0; 1259 box.height = outp->bitstream->height0; 1260 box.depth = outp->bitstream->depth0; 1261 1262 output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, 1263 PIPE_TRANSFER_READ_WRITE, 1264 &box, &outp->transfer); 1265 1266 /* ------------- get size of result ----------------- */ 1267 1268 priv->codec->get_feedback(priv->codec, task->feedback, &size); 1269 1270 output->nOffset = 0; 1271 output->nFilledLen = size; /* mark buffer as full */ 1272 } 1273