VideoEditorVideoEncoder.cpp revision 7c9d8018755adf1857571125ba1b3598c96ea506
1/* 2 * Copyright (C) 2011 NXP Software 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18************************************************************************* 19* @file VideoEditorVideoEncoder.cpp 20* @brief StageFright shell video encoder 21************************************************************************* 22*/ 23#define LOG_NDEBUG 1 24#define LOG_TAG "VIDEOEDITOR_VIDEOENCODER" 25 26/******************* 27 * HEADERS * 28 *******************/ 29#include "M4OSA_Debug.h" 30#include "M4SYS_AccessUnit.h" 31#include "VideoEditorVideoEncoder.h" 32#include "VideoEditorUtils.h" 33 34#include "utils/Log.h" 35#include <media/stagefright/MediaSource.h> 36#include <media/stagefright/MediaDebug.h> 37#include <media/stagefright/MediaDefs.h> 38#include <media/stagefright/MetaData.h> 39#include <media/stagefright/OMXClient.h> 40#include <media/stagefright/OMXCodec.h> 41#include "OMX_Video.h" 42 43/******************** 44 * DEFINITIONS * 45 ********************/ 46 47// Minimum number of buffer in the source in order to allow encoding 48#define VIDEOEDITOR_MIN_BUFFER_NB 15 49 50// Not enough source buffers available 51#define M4WAR_SF_LOW_BUFFER M4OSA_ERR_CREATE(M4_WAR, 0xFF, 0x00001) 52 53// Encoder color format 54#define VIDEOEDITOR_ENCODER_COLOR_FORMAT OMX_COLOR_FormatYUV420Planar 55 56// Force using hardware encoder 57#define VIDEOEDITOR_FORCECODEC kHardwareCodecsOnly 58 59// Force Encoder to produce a DSI by sending fake input frames upon creation 60#define VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION 61 62#if defined(VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION) && \ 63 !defined(VIDEOEDITOR_FORCECODEC) 64 #error "Cannot force DSI retrieval if codec type is not fixed" 65#endif 66 67/******************** 68 * SOURCE CLASS * 69 ********************/ 70 71namespace android { 72 73struct VideoEditorVideoEncoderSource : public MediaSource { 74 public: 75 static sp<VideoEditorVideoEncoderSource> Create(); 76 virtual status_t start(MetaData *params = NULL); 77 virtual status_t stop(); 78 virtual sp<MetaData> getFormat(); 79 virtual status_t read(MediaBuffer **buffer, 80 const ReadOptions *options = NULL); 81 virtual int32_t storeBuffer(MediaBuffer *buffer); 82 83 protected: 84 virtual ~VideoEditorVideoEncoderSource(); 85 86 private: 87 struct MediaBufferChain { 88 MediaBuffer* buffer; 89 MediaBufferChain* nextLink; 90 }; 91 enum State { 92 CREATED, 93 STARTED, 94 ERROR 95 }; 96 VideoEditorVideoEncoderSource(); 97 MediaBufferChain* mFirstBufferLink; 98 MediaBufferChain* mLastBufferLink; 99 int32_t mNbBuffer; 100 bool mIsEOS; 101 State mState; 102}; 103 104sp<VideoEditorVideoEncoderSource> VideoEditorVideoEncoderSource::Create() { 105 106 sp<VideoEditorVideoEncoderSource> aSource = 107 new VideoEditorVideoEncoderSource(); 108 return aSource; 109} 110 111VideoEditorVideoEncoderSource::VideoEditorVideoEncoderSource(): 112 mFirstBufferLink(NULL), 113 mLastBufferLink(NULL), 114 mNbBuffer(0), 115 mIsEOS(false), 116 mState(CREATED) { 117 LOGV("VideoEditorVideoEncoderSource::VideoEditorVideoEncoderSource"); 118} 119 120VideoEditorVideoEncoderSource::~VideoEditorVideoEncoderSource() { 121 122 // Safety clean up 123 if( STARTED == mState ) { 124 stop(); 125 } 126} 127 128status_t VideoEditorVideoEncoderSource::start(MetaData *meta) { 129 status_t err = OK; 130 131 LOGV("VideoEditorVideoEncoderSource::start() begin"); 132 133 if( CREATED != mState ) { 134 LOGV("VideoEditorVideoEncoderSource::start: invalid state %d", mState); 135 return UNKNOWN_ERROR; 136 } 137 mState = STARTED; 138 139 LOGV("VideoEditorVideoEncoderSource::start() END (0x%x)", err); 140 return err; 141} 142 143status_t VideoEditorVideoEncoderSource::stop() { 144 status_t err = OK; 145 146 LOGV("VideoEditorVideoEncoderSource::stop() begin"); 147 148 if( STARTED != mState ) { 149 LOGV("VideoEditorVideoEncoderSource::stop: invalid state %d", mState); 150 return UNKNOWN_ERROR; 151 } 152 153 // Release the buffer chain 154 int32_t i = 0; 155 MediaBufferChain* tmpLink = NULL; 156 while( mFirstBufferLink ) { 157 i++; 158 tmpLink = mFirstBufferLink; 159 mFirstBufferLink = mFirstBufferLink->nextLink; 160 delete tmpLink; 161 } 162 LOGV("VideoEditorVideoEncoderSource::stop : %d buffer remained", i); 163 mFirstBufferLink = NULL; 164 mLastBufferLink = NULL; 165 166 mState = CREATED; 167 168 LOGV("VideoEditorVideoEncoderSource::stop() END (0x%x)", err); 169 return err; 170} 171 172sp<MetaData> VideoEditorVideoEncoderSource::getFormat() { 173 174 LOGW("VideoEditorVideoEncoderSource::getFormat:THIS IS NOT IMPLEMENTED"); 175 return NULL; 176} 177 178status_t VideoEditorVideoEncoderSource::read(MediaBuffer **buffer, 179 const ReadOptions *options) { 180 MediaSource::ReadOptions readOptions; 181 status_t err = OK; 182 MediaBufferChain* tmpLink = NULL; 183 184 LOGV("VideoEditorVideoEncoderSource::read() begin"); 185 186 if ( STARTED != mState ) { 187 LOGV("VideoEditorVideoEncoderSource::read: invalid state %d", mState); 188 return UNKNOWN_ERROR; 189 } 190 191 // Get a buffer from the chain 192 if ( NULL == mFirstBufferLink ) { 193 *buffer = NULL; 194 if( mIsEOS ) { 195 LOGV("VideoEditorVideoEncoderSource::read : EOS"); 196 return ERROR_END_OF_STREAM; 197 } else { 198 LOGV("VideoEditorVideoEncoderSource::read: no buffer available"); 199 return ERROR_END_OF_STREAM; 200 } 201 } 202 *buffer = mFirstBufferLink->buffer; 203 tmpLink = mFirstBufferLink; 204 mFirstBufferLink = mFirstBufferLink->nextLink; 205 206 if ( NULL == mFirstBufferLink ) { 207 mLastBufferLink = NULL; 208 } 209 delete tmpLink; 210 mNbBuffer--; 211 212 LOGV("VideoEditorVideoEncoderSource::read() END (0x%x)", err); 213 return err; 214} 215 216int32_t VideoEditorVideoEncoderSource::storeBuffer(MediaBuffer *buffer) { 217 status_t err = OK; 218 219 LOGV("VideoEditorVideoEncoderSource::storeBuffer() begin"); 220 221 if( NULL == buffer ) { 222 LOGV("VideoEditorVideoEncoderSource::storeBuffer : reached EOS"); 223 mIsEOS = true; 224 } else { 225 MediaBufferChain* newLink = new MediaBufferChain; 226 newLink->buffer = buffer; 227 newLink->nextLink = NULL; 228 if( NULL != mLastBufferLink ) { 229 mLastBufferLink->nextLink = newLink; 230 } else { 231 mFirstBufferLink = newLink; 232 } 233 mLastBufferLink = newLink; 234 mNbBuffer++; 235 } 236 LOGV("VideoEditorVideoEncoderSource::storeBuffer() end"); 237 return mNbBuffer; 238} 239 240/** 241 ****************************************************************************** 242 * structure VideoEditorVideoEncoder_Context 243 * @brief This structure defines the context of the StageFright video encoder 244 * shell 245 ****************************************************************************** 246*/ 247typedef enum { 248 CREATED = 0x1, 249 OPENED = 0x2, 250 STARTED = 0x4, 251 BUFFERING = 0x8, 252 READING = 0x10 253} VideoEditorVideoEncoder_State; 254 255typedef struct { 256 VideoEditorVideoEncoder_State mState; 257 M4ENCODER_Format mFormat; 258 M4WRITER_DataInterface* mWriterDataInterface; 259 M4VPP_apply_fct* mPreProcFunction; 260 M4VPP_Context mPreProcContext; 261 M4SYS_AccessUnit* mAccessUnit; 262 M4ENCODER_Params* mCodecParams; 263 M4ENCODER_Header mHeader; 264 H264MCS_ProcessEncodedNALU_fct* mH264NALUPostProcessFct; 265 M4OSA_Context mH264NALUPostProcessCtx; 266 M4OSA_UInt32 mLastCTS; 267 sp<VideoEditorVideoEncoderSource> mEncoderSource; 268 OMXClient mClient; 269 sp<MediaSource> mEncoder; 270 OMX_COLOR_FORMATTYPE mEncoderColorFormat; 271 272 uint32_t mNbInputFrames; 273 double mFirstInputCts; 274 double mLastInputCts; 275 uint32_t mNbOutputFrames; 276 int64_t mFirstOutputCts; 277 int64_t mLastOutputCts; 278 279} VideoEditorVideoEncoder_Context; 280 281/******************** 282 * TOOLS * 283 ********************/ 284 285M4OSA_ERR VideoEditorVideoEncoder_getDSI(M4ENCODER_Context pContext, 286 sp<MetaData> metaData) { 287 M4OSA_ERR err = M4NO_ERROR; 288 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 289 status_t result = OK; 290 int32_t nbBuffer = 0; 291 int32_t stride = 0; 292 int32_t height = 0; 293 int32_t framerate = 0; 294 int32_t isCodecConfig = 0; 295 size_t size = 0; 296 uint32_t codecFlags = 0; 297 MediaBuffer* inputBuffer = NULL; 298 MediaBuffer* outputBuffer = NULL; 299 sp<VideoEditorVideoEncoderSource> encoderSource = NULL; 300 sp<MediaSource> encoder = NULL;; 301 OMXClient client; 302 303 LOGV("VideoEditorVideoEncoder_getDSI begin"); 304 // Input parameters check 305 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 306 VIDEOEDITOR_CHECK(M4OSA_NULL != metaData.get(), M4ERR_PARAMETER); 307 308 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 309 VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE); 310 311 // Create the encoder source 312 encoderSource = VideoEditorVideoEncoderSource::Create(); 313 VIDEOEDITOR_CHECK(NULL != encoderSource.get(), M4ERR_STATE); 314 315 // Connect to the OMX client 316 result = client.connect(); 317 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 318 319 // Create the OMX codec 320 // VIDEOEDITOR_FORCECODEC MUST be defined here 321 codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC; 322 encoder = OMXCodec::Create(client.interface(), metaData, true, 323 encoderSource, NULL, codecFlags); 324 VIDEOEDITOR_CHECK(NULL != encoder.get(), M4ERR_STATE); 325 326 /** 327 * Send fake frames and retrieve the DSI 328 */ 329 // Send a fake frame to the source 330 metaData->findInt32(kKeyStride, &stride); 331 metaData->findInt32(kKeyHeight, &height); 332 metaData->findInt32(kKeySampleRate, &framerate); 333 size = (size_t)(stride*height*3)/2; 334 inputBuffer = new MediaBuffer(size); 335 inputBuffer->meta_data()->setInt64(kKeyTime, 0); 336 nbBuffer = encoderSource->storeBuffer(inputBuffer); 337 encoderSource->storeBuffer(NULL); // Signal EOS 338 339 // Call read once to get the DSI 340 result = encoder->start();; 341 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 342 result = encoder->read(&outputBuffer, NULL); 343 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 344 VIDEOEDITOR_CHECK(outputBuffer->meta_data()->findInt32( 345 kKeyIsCodecConfig, &isCodecConfig) && isCodecConfig, M4ERR_STATE); 346 347 VIDEOEDITOR_CHECK(M4OSA_NULL == pEncoderContext->mHeader.pBuf, M4ERR_STATE); 348 if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) { 349 // For H264, format the DSI 350 result = buildAVCCodecSpecificData( 351 (uint8_t**)(&(pEncoderContext->mHeader.pBuf)), 352 (size_t*)(&(pEncoderContext->mHeader.Size)), 353 (const uint8_t*)outputBuffer->data() + outputBuffer->range_offset(), 354 outputBuffer->range_length(), encoder->getFormat().get()); 355 outputBuffer->release(); 356 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 357 } else { 358 // For MPEG4, just copy the DSI 359 pEncoderContext->mHeader.Size = 360 (M4OSA_UInt32)outputBuffer->range_length(); 361 SAFE_MALLOC(pEncoderContext->mHeader.pBuf, M4OSA_Int8, 362 pEncoderContext->mHeader.Size, "Encoder header"); 363 M4OSA_memcpy(pEncoderContext->mHeader.pBuf, 364 (M4OSA_MemAddr8)(outputBuffer->data())+outputBuffer->range_offset(), 365 pEncoderContext->mHeader.Size); 366 outputBuffer->release(); 367 } 368 369 result = encoder->stop(); 370 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 371 372cleanUp: 373 // Destroy the graph 374 if ( encoder != NULL ) { encoder.clear(); } 375 client.disconnect(); 376 if ( encoderSource != NULL ) { encoderSource.clear(); } 377 if ( M4NO_ERROR == err ) { 378 LOGV("VideoEditorVideoEncoder_getDSI no error"); 379 } else { 380 LOGV("VideoEditorVideoEncoder_getDSI ERROR 0x%X", err); 381 } 382 LOGV("VideoEditorVideoEncoder_getDSI end"); 383 return err; 384} 385/******************** 386 * ENGINE INTERFACE * 387 ********************/ 388 389M4OSA_ERR VideoEditorVideoEncoder_cleanup(M4ENCODER_Context pContext) { 390 M4OSA_ERR err = M4NO_ERROR; 391 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 392 393 LOGV("VideoEditorVideoEncoder_cleanup begin"); 394 // Input parameters check 395 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 396 397 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 398 VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE); 399 400 // Release memory 401 SAFE_FREE(pEncoderContext->mHeader.pBuf); 402 SAFE_FREE(pEncoderContext); 403 pContext = M4OSA_NULL; 404 405cleanUp: 406 if ( M4NO_ERROR == err ) { 407 LOGV("VideoEditorVideoEncoder_cleanup no error"); 408 } else { 409 LOGV("VideoEditorVideoEncoder_cleanup ERROR 0x%X", err); 410 } 411 LOGV("VideoEditorVideoEncoder_cleanup end"); 412 return err; 413} 414 415M4OSA_ERR VideoEditorVideoEncoder_init(M4ENCODER_Format format, 416 M4ENCODER_Context* pContext, 417 M4WRITER_DataInterface* pWriterDataInterface, 418 M4VPP_apply_fct* pVPPfct, M4VPP_Context pVPPctxt, 419 M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData) { 420 421 M4OSA_ERR err = M4NO_ERROR; 422 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 423 424 LOGV("VideoEditorVideoEncoder_init begin: format %d", format); 425 // Input parameters check 426 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 427 VIDEOEDITOR_CHECK(M4OSA_NULL != pWriterDataInterface, M4ERR_PARAMETER); 428 VIDEOEDITOR_CHECK(M4OSA_NULL != pVPPfct, M4ERR_PARAMETER); 429 VIDEOEDITOR_CHECK(M4OSA_NULL != pVPPctxt, M4ERR_PARAMETER); 430 431 // Context allocation & initialization 432 SAFE_MALLOC(pEncoderContext, VideoEditorVideoEncoder_Context, 1, 433 "VideoEditorVideoEncoder"); 434 pEncoderContext->mState = CREATED; 435 pEncoderContext->mFormat = format; 436 pEncoderContext->mWriterDataInterface = pWriterDataInterface; 437 pEncoderContext->mPreProcFunction = pVPPfct; 438 pEncoderContext->mPreProcContext = pVPPctxt; 439 440 *pContext = pEncoderContext; 441 442cleanUp: 443 if ( M4NO_ERROR == err ) { 444 LOGV("VideoEditorVideoEncoder_init no error"); 445 } else { 446 VideoEditorVideoEncoder_cleanup(pEncoderContext); 447 *pContext = M4OSA_NULL; 448 LOGV("VideoEditorVideoEncoder_init ERROR 0x%X", err); 449 } 450 LOGV("VideoEditorVideoEncoder_init end"); 451 return err; 452} 453 454M4OSA_ERR VideoEditorVideoEncoder_init_H263(M4ENCODER_Context* pContext, 455 M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct, 456 M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData) 457 { 458 459 return VideoEditorVideoEncoder_init(M4ENCODER_kH263, pContext, 460 pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData); 461} 462 463 464M4OSA_ERR VideoEditorVideoEncoder_init_MPEG4(M4ENCODER_Context* pContext, 465 M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct, 466 M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData) 467 { 468 469 return VideoEditorVideoEncoder_init(M4ENCODER_kMPEG4, pContext, 470 pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData); 471} 472 473 474M4OSA_ERR VideoEditorVideoEncoder_init_H264(M4ENCODER_Context* pContext, 475 M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct, 476 M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData) 477 { 478 479 return VideoEditorVideoEncoder_init(M4ENCODER_kH264, pContext, 480 pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData); 481} 482 483M4OSA_ERR VideoEditorVideoEncoder_close(M4ENCODER_Context pContext) { 484 M4OSA_ERR err = M4NO_ERROR; 485 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 486 487 LOGV("VideoEditorVideoEncoder_close begin"); 488 // Input parameters check 489 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 490 491 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 492 VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE); 493 494 // Release memory 495 SAFE_FREE(pEncoderContext->mCodecParams); 496 497 // Destroy the graph 498 pEncoderContext->mEncoder.clear(); 499 pEncoderContext->mClient.disconnect(); 500 pEncoderContext->mEncoderSource.clear(); 501 502 // Set the new state 503 pEncoderContext->mState = CREATED; 504 505cleanUp: 506 if( M4NO_ERROR == err ) { 507 LOGV("VideoEditorVideoEncoder_close no error"); 508 } else { 509 LOGV("VideoEditorVideoEncoder_close ERROR 0x%X", err); 510 } 511 LOGV("VideoEditorVideoEncoder_close end"); 512 return err; 513} 514 515 516M4OSA_ERR VideoEditorVideoEncoder_open(M4ENCODER_Context pContext, 517 M4SYS_AccessUnit* pAU, M4OSA_Void* pParams) { 518 M4OSA_ERR err = M4NO_ERROR; 519 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 520 M4ENCODER_Params* pCodecParams = M4OSA_NULL; 521 status_t result = OK; 522 sp<MetaData> encoderMetadata = NULL; 523 const char* mime = NULL; 524 int32_t iProfile = 0; 525 int32_t iFrameRate = 0; 526 uint32_t codecFlags = 0; 527 528 LOGV(">>> VideoEditorVideoEncoder_open begin"); 529 // Input parameters check 530 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 531 VIDEOEDITOR_CHECK(M4OSA_NULL != pAU, M4ERR_PARAMETER); 532 VIDEOEDITOR_CHECK(M4OSA_NULL != pParams, M4ERR_PARAMETER); 533 534 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 535 pCodecParams = (M4ENCODER_Params*)pParams; 536 VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE); 537 538 // Context initialization 539 pEncoderContext->mAccessUnit = pAU; 540 541 // Allocate & initialize the encoding parameters 542 SAFE_MALLOC(pEncoderContext->mCodecParams, M4ENCODER_Params, 1, 543 "VideoEditorVideoEncoder"); 544 545 546 pEncoderContext->mCodecParams->InputFormat = pCodecParams->InputFormat; 547 pEncoderContext->mCodecParams->InputFrameWidth = 548 pCodecParams->InputFrameWidth; 549 pEncoderContext->mCodecParams->InputFrameHeight = 550 pCodecParams->InputFrameHeight; 551 pEncoderContext->mCodecParams->FrameWidth = pCodecParams->FrameWidth; 552 pEncoderContext->mCodecParams->FrameHeight = pCodecParams->FrameHeight; 553 pEncoderContext->mCodecParams->Bitrate = pCodecParams->Bitrate; 554 pEncoderContext->mCodecParams->FrameRate = pCodecParams->FrameRate; 555 pEncoderContext->mCodecParams->Format = pCodecParams->Format; 556 557 // Check output format consistency and resolution 558 VIDEOEDITOR_CHECK( 559 pEncoderContext->mCodecParams->Format == pEncoderContext->mFormat, 560 M4ERR_PARAMETER); 561 VIDEOEDITOR_CHECK(0 == pEncoderContext->mCodecParams->FrameWidth % 16, 562 M4ERR_PARAMETER); 563 VIDEOEDITOR_CHECK(0 == pEncoderContext->mCodecParams->FrameHeight % 16, 564 M4ERR_PARAMETER); 565 566 /** 567 * StageFright graph building 568 */ 569 570 // Create the meta data for the encoder 571 encoderMetadata = new MetaData; 572 switch( pEncoderContext->mCodecParams->Format ) { 573 case M4ENCODER_kH263: 574 mime = MEDIA_MIMETYPE_VIDEO_H263; 575 iProfile = OMX_VIDEO_H263ProfileBaseline; 576 break; 577 case M4ENCODER_kMPEG4: 578 mime = MEDIA_MIMETYPE_VIDEO_MPEG4; 579 iProfile = OMX_VIDEO_MPEG4ProfileSimple; 580 break; 581 case M4ENCODER_kH264: 582 mime = MEDIA_MIMETYPE_VIDEO_AVC; 583 iProfile = OMX_VIDEO_AVCProfileBaseline; 584 break; 585 default: 586 VIDEOEDITOR_CHECK(!"VideoEncoder_open : incorrect input format", 587 M4ERR_PARAMETER); 588 break; 589 } 590 encoderMetadata->setCString(kKeyMIMEType, mime); 591 encoderMetadata->setInt32(kKeyVideoProfile, iProfile); 592 encoderMetadata->setInt32(kKeyWidth, 593 (int32_t)pEncoderContext->mCodecParams->FrameWidth); 594 encoderMetadata->setInt32(kKeyStride, 595 (int32_t)pEncoderContext->mCodecParams->FrameWidth); 596 encoderMetadata->setInt32(kKeyHeight, 597 (int32_t)pEncoderContext->mCodecParams->FrameHeight); 598 encoderMetadata->setInt32(kKeySliceHeight, 599 (int32_t)pEncoderContext->mCodecParams->FrameHeight); 600 601 switch( pEncoderContext->mCodecParams->FrameRate ) { 602 case M4ENCODER_k5_FPS: iFrameRate = 5; break; 603 case M4ENCODER_k7_5_FPS: iFrameRate = 8; break; 604 case M4ENCODER_k10_FPS: iFrameRate = 10; break; 605 case M4ENCODER_k12_5_FPS: iFrameRate = 13; break; 606 case M4ENCODER_k15_FPS: iFrameRate = 15; break; 607 case M4ENCODER_k20_FPS: iFrameRate = 20; break; 608 case M4ENCODER_k25_FPS: iFrameRate = 25; break; 609 case M4ENCODER_k30_FPS: iFrameRate = 30; break; 610 case M4ENCODER_kVARIABLE_FPS: 611 iFrameRate = 30; 612 LOGI("Frame rate set to M4ENCODER_kVARIABLE_FPS: set to 30"); 613 break; 614 case M4ENCODER_kUSE_TIMESCALE: 615 iFrameRate = 30; 616 LOGI("Frame rate set to M4ENCODER_kUSE_TIMESCALE: set to 30"); 617 break; 618 619 default: 620 VIDEOEDITOR_CHECK(!"VideoEncoder_open:incorrect framerate", 621 M4ERR_STATE); 622 break; 623 } 624 encoderMetadata->setInt32(kKeyFrameRate, iFrameRate); 625 encoderMetadata->setInt32(kKeyBitRate, 626 (int32_t)pEncoderContext->mCodecParams->Bitrate); 627 encoderMetadata->setInt32(kKeyIFramesInterval, 1); 628 629 pEncoderContext->mEncoderColorFormat = VIDEOEDITOR_ENCODER_COLOR_FORMAT; 630 encoderMetadata->setInt32(kKeyColorFormat, 631 pEncoderContext->mEncoderColorFormat); 632 633#ifdef VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION 634 // Get the encoder DSI 635 err = VideoEditorVideoEncoder_getDSI(pEncoderContext, encoderMetadata); 636 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 637#endif /* VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION */ 638 639 // Create the encoder source 640 pEncoderContext->mEncoderSource = VideoEditorVideoEncoderSource::Create(); 641 VIDEOEDITOR_CHECK( 642 NULL != pEncoderContext->mEncoderSource.get(), M4ERR_STATE); 643 644 // Connect to the OMX client 645 result = pEncoderContext->mClient.connect(); 646 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 647 648 // Create the OMX codec 649#ifdef VIDEOEDITOR_FORCECODEC 650 codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC; 651#endif /* VIDEOEDITOR_FORCECODEC */ 652 pEncoderContext->mEncoder = OMXCodec::Create( 653 pEncoderContext->mClient.interface(), encoderMetadata, true, 654 pEncoderContext->mEncoderSource, NULL, codecFlags); 655 VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoder.get(), M4ERR_STATE); 656 LOGV("VideoEditorVideoEncoder_open : DONE"); 657 658 // Set the new state 659 pEncoderContext->mState = OPENED; 660 661cleanUp: 662 if( M4NO_ERROR == err ) { 663 LOGV("VideoEditorVideoEncoder_open no error"); 664 } else { 665 VideoEditorVideoEncoder_close(pEncoderContext); 666 LOGV("VideoEditorVideoEncoder_open ERROR 0x%X", err); 667 } 668 LOGV("VideoEditorVideoEncoder_open end"); 669 return err; 670} 671 672M4OSA_ERR VideoEditorVideoEncoder_processOutputBuffer( 673 M4ENCODER_Context pContext, MediaBuffer* buffer); 674M4OSA_ERR VideoEditorVideoEncoder_processInputBuffer( 675 M4ENCODER_Context pContext, M4OSA_Double Cts, 676 M4OSA_Bool bReachedEOS) { 677 M4OSA_ERR err = M4NO_ERROR; 678 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 679 M4VIFI_ImagePlane pOutPlane[3]; 680 MediaBuffer* buffer = NULL; 681 int32_t nbBuffer = 0; 682 683 LOGV("VideoEditorVideoEncoder_processInputBuffer begin: cts %f", Cts); 684 // Input parameters check 685 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 686 687 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 688 pOutPlane[0].pac_data = M4OSA_NULL; 689 pOutPlane[1].pac_data = M4OSA_NULL; 690 pOutPlane[2].pac_data = M4OSA_NULL; 691 692 if ( M4OSA_FALSE == bReachedEOS ) { 693 M4OSA_UInt32 sizeY = pEncoderContext->mCodecParams->FrameWidth * 694 pEncoderContext->mCodecParams->FrameHeight; 695 M4OSA_UInt32 sizeU = sizeY >> 2; 696 M4OSA_UInt32 size = sizeY + 2*sizeU; 697 M4OSA_UInt8* pData = M4OSA_NULL; 698 buffer = new MediaBuffer((size_t)size); 699 pData = (M4OSA_UInt8*)buffer->data() + buffer->range_offset(); 700 701 // Prepare the output image for pre-processing 702 pOutPlane[0].u_width = pEncoderContext->mCodecParams->FrameWidth; 703 pOutPlane[0].u_height = pEncoderContext->mCodecParams->FrameHeight; 704 pOutPlane[0].u_topleft = 0; 705 pOutPlane[0].u_stride = pOutPlane[0].u_width; 706 pOutPlane[1].u_width = pOutPlane[0].u_width/2; 707 pOutPlane[1].u_height = pOutPlane[0].u_height/2; 708 pOutPlane[1].u_topleft = 0; 709 pOutPlane[1].u_stride = pOutPlane[0].u_stride/2; 710 pOutPlane[2].u_width = pOutPlane[1].u_width; 711 pOutPlane[2].u_height = pOutPlane[1].u_height; 712 pOutPlane[2].u_topleft = 0; 713 pOutPlane[2].u_stride = pOutPlane[1].u_stride; 714 715 switch( pEncoderContext->mEncoderColorFormat ) { 716 case OMX_COLOR_FormatYUV420Planar: 717 pOutPlane[0].pac_data = pData; 718 pOutPlane[1].pac_data = pData + sizeY; 719 pOutPlane[2].pac_data = pData + sizeY + sizeU; 720 break; 721 case OMX_COLOR_FormatYUV420SemiPlanar: 722 pOutPlane[0].pac_data = pData; 723 SAFE_MALLOC(pOutPlane[1].pac_data, M4VIFI_UInt8, 724 pOutPlane[1].u_height*pOutPlane[1].u_stride,"OutputPlaneU"); 725 SAFE_MALLOC(pOutPlane[2].pac_data, M4VIFI_UInt8, 726 pOutPlane[2].u_height*pOutPlane[2].u_stride,"OutputPlaneV"); 727 break; 728 default: 729 LOGV("VideoEditorVideoEncoder_processInputBuffer : unsupported " 730 "color format 0x%X", pEncoderContext->mEncoderColorFormat); 731 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER); 732 break; 733 } 734 735 // Apply pre-processing 736 err = pEncoderContext->mPreProcFunction( 737 pEncoderContext->mPreProcContext, M4OSA_NULL, pOutPlane); 738 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 739 740 // Convert to MediaBuffer format if necessary 741 if( OMX_COLOR_FormatYUV420SemiPlanar == \ 742 pEncoderContext->mEncoderColorFormat ) { 743 M4OSA_UInt8* pTmpData = M4OSA_NULL; 744 pTmpData = pData + sizeY; 745 // Highly unoptimized copy... 746 for( M4OSA_UInt32 i=0; i<sizeU; i++ ) { 747 *pTmpData = pOutPlane[2].pac_data[i]; pTmpData++; 748 *pTmpData = pOutPlane[1].pac_data[i]; pTmpData++; 749 } 750 } 751 752 // Set the metadata 753 buffer->meta_data()->setInt64(kKeyTime, (int64_t)(Cts*1000)); 754 } 755 756 // Push the buffer to the source, a NULL buffer, notifies the source of EOS 757 nbBuffer = pEncoderContext->mEncoderSource->storeBuffer(buffer); 758 if ( VIDEOEDITOR_MIN_BUFFER_NB > nbBuffer ) { 759 LOGV("VideoEncoder_processInputBuffer not enough source buffer" 760 "%d", nbBuffer); 761 err = M4WAR_SF_LOW_BUFFER; 762 } 763 764cleanUp: 765 if ( OMX_COLOR_FormatYUV420SemiPlanar == \ 766 pEncoderContext->mEncoderColorFormat ) { 767 // Y plane has not been allocated 768 if ( pOutPlane[1].pac_data ) { 769 SAFE_FREE(pOutPlane[1].pac_data); 770 } 771 if ( pOutPlane[2].pac_data ) { 772 SAFE_FREE(pOutPlane[2].pac_data); 773 } 774 } 775 if ( (M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err) ) { 776 LOGV("VideoEditorVideoEncoder_processInputBuffer error 0x%X", err); 777 } else { 778 if( NULL != buffer ) { 779 buffer->release(); 780 } 781 LOGV("VideoEditorVideoEncoder_processInputBuffer ERROR 0x%X", err); 782 } 783 LOGV("VideoEditorVideoEncoder_processInputBuffer end"); 784 return err; 785} 786 787M4OSA_ERR VideoEditorVideoEncoder_processOutputBuffer( 788 M4ENCODER_Context pContext, MediaBuffer* buffer) { 789 M4OSA_ERR err = M4NO_ERROR; 790 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 791 M4OSA_UInt32 Cts = 0; 792 int32_t i32Tmp = 0; 793 int64_t i64Tmp = 0; 794 status_t result = OK; 795 796 LOGV("VideoEditorVideoEncoder_processOutputBuffer begin"); 797 // Input parameters check 798 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 799 VIDEOEDITOR_CHECK(M4OSA_NULL != buffer, M4ERR_PARAMETER); 800 801 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 802 803 // Process the returned AU 804 if ( 0 == buffer->range_length() ) { 805 // Encoder has no data yet, nothing unusual 806 LOGV("VideoEditorVideoEncoder_processOutputBuffer : buffer is empty"); 807 goto cleanUp; 808 } 809 VIDEOEDITOR_CHECK(0 == ((M4OSA_UInt32)buffer->data())%4, M4ERR_PARAMETER); 810 VIDEOEDITOR_CHECK(buffer->meta_data().get(), M4ERR_PARAMETER); 811 if ( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ){ 812#if 1 813 { // Display the DSI 814 LOGV("VideoEditorVideoEncoder_processOutputBuffer DSI %d", 815 buffer->range_length()); 816 uint8_t* tmp = (uint8_t*)(buffer->data()); 817 for( uint32_t i=0; i<buffer->range_length(); i++ ) { 818 LOGV("DSI [%d] %.2X", i, tmp[i]); 819 } 820 } 821#endif 822 823#ifndef VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION 824 VIDEOEDITOR_CHECK(M4OSA_NULL == pEncoderContext->mHeader.pBuf, 825 M4ERR_STATE); 826 if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) { 827 result = buildAVCCodecSpecificData( 828 (uint8_t**)(&(pEncoderContext->mHeader.pBuf)), 829 (size_t*)(&(pEncoderContext->mHeader.Size)), 830 (const uint8_t *)buffer->data() + buffer->range_offset(), 831 buffer->range_length(), 832 pEncoderContext->mEncoder->getFormat().get()); 833 } else { 834 pEncoderContext->mHeader.Size = 835 (M4OSA_UInt32)buffer->range_length(); 836 SAFE_MALLOC(pEncoderContext->mHeader.pBuf, M4OSA_Int8, 837 pEncoderContext->mHeader.Size, "Encoder header"); 838 M4OSA_memcpy(pEncoderContext->mHeader.pBuf, 839 (M4OSA_MemAddr8)(buffer->data())+buffer->range_offset(), 840 pEncoderContext->mHeader.Size); 841 } 842#endif /* VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION */ 843 } else { 844 // Check the CTS 845 VIDEOEDITOR_CHECK(buffer->meta_data()->findInt64(kKeyTime, &i64Tmp), 846 M4ERR_STATE); 847 848 pEncoderContext->mNbOutputFrames++; 849 if ( 0 > pEncoderContext->mFirstOutputCts ) { 850 pEncoderContext->mFirstOutputCts = i64Tmp; 851 } 852 pEncoderContext->mLastOutputCts = i64Tmp; 853 854 Cts = (M4OSA_Int32)(i64Tmp/1000); 855 LOGV("[TS_CHECK] VI/ENC WRITE frame %d @ %lld -> %d (last %d)", 856 pEncoderContext->mNbOutputFrames, i64Tmp, Cts, 857 pEncoderContext->mLastCTS); 858 if ( Cts < pEncoderContext->mLastCTS ) { 859 LOGV("VideoEncoder_processOutputBuffer WARNING : Cts is going " 860 "backwards %d < %d", Cts, pEncoderContext->mLastCTS); 861 goto cleanUp; 862 } 863 LOGV("VideoEditorVideoEncoder_processOutputBuffer : %d %d", 864 Cts, pEncoderContext->mLastCTS); 865 866 // Retrieve the AU container 867 err = pEncoderContext->mWriterDataInterface->pStartAU( 868 pEncoderContext->mWriterDataInterface->pWriterContext, 869 pEncoderContext->mAccessUnit->stream->streamID, 870 pEncoderContext->mAccessUnit); 871 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 872 873 // Format the AU 874 VIDEOEDITOR_CHECK( 875 buffer->range_length() <= pEncoderContext->mAccessUnit->size, 876 M4ERR_PARAMETER); 877 // Remove H264 AU start code 878 if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) { 879 if (!memcmp((const uint8_t *)buffer->data() + \ 880 buffer->range_offset(), "\x00\x00\x00\x01", 4) ) { 881 buffer->set_range(buffer->range_offset() + 4, 882 buffer->range_length() - 4); 883 } 884 } 885 886 if ( (M4ENCODER_kH264 == pEncoderContext->mFormat) && 887 (M4OSA_NULL != pEncoderContext->mH264NALUPostProcessFct) ) { 888 // H264 trimming case, NALU post processing is needed 889 M4OSA_Int32 outputSize = pEncoderContext->mAccessUnit->size; 890 err = pEncoderContext->mH264NALUPostProcessFct( 891 pEncoderContext->mH264NALUPostProcessCtx, 892 (M4OSA_UInt8*)buffer->data()+buffer->range_offset(), 893 buffer->range_length(), 894 (M4OSA_UInt8*)pEncoderContext->mAccessUnit->dataAddress, 895 &outputSize); 896 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 897 pEncoderContext->mAccessUnit->size = (M4OSA_UInt32)outputSize; 898 } else { 899 // The AU can just be copied 900 M4OSA_memcpy((M4OSA_MemAddr8)pEncoderContext->mAccessUnit->\ 901 dataAddress, (M4OSA_MemAddr8)(buffer->data())+buffer->\ 902 range_offset(), buffer->range_length()); 903 pEncoderContext->mAccessUnit->size = 904 (M4OSA_UInt32)buffer->range_length(); 905 } 906 907 if ( buffer->meta_data()->findInt32(kKeyIsSyncFrame,&i32Tmp) && i32Tmp){ 908 pEncoderContext->mAccessUnit->attribute = AU_RAP; 909 } else { 910 pEncoderContext->mAccessUnit->attribute = AU_B_Frame; 911 } 912 pEncoderContext->mLastCTS = Cts; 913 pEncoderContext->mAccessUnit->CTS = Cts; 914 pEncoderContext->mAccessUnit->DTS = Cts; 915 916 LOGV("VideoEditorVideoEncoder_processOutputBuffer: AU @ 0x%X 0x%X %d %d", 917 pEncoderContext->mAccessUnit->dataAddress, 918 *pEncoderContext->mAccessUnit->dataAddress, 919 pEncoderContext->mAccessUnit->size, 920 pEncoderContext->mAccessUnit->CTS); 921 922 // Write the AU 923 err = pEncoderContext->mWriterDataInterface->pProcessAU( 924 pEncoderContext->mWriterDataInterface->pWriterContext, 925 pEncoderContext->mAccessUnit->stream->streamID, 926 pEncoderContext->mAccessUnit); 927 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 928 } 929 930cleanUp: 931 buffer->release(); 932 if( M4NO_ERROR == err ) { 933 LOGV("VideoEditorVideoEncoder_processOutputBuffer no error"); 934 } else { 935 SAFE_FREE(pEncoderContext->mHeader.pBuf); 936 pEncoderContext->mHeader.Size = 0; 937 LOGV("VideoEditorVideoEncoder_processOutputBuffer ERROR 0x%X", err); 938 } 939 LOGV("VideoEditorVideoEncoder_processOutputBuffer end"); 940 return err; 941} 942 943M4OSA_ERR VideoEditorVideoEncoder_encode(M4ENCODER_Context pContext, 944 M4VIFI_ImagePlane* pInPlane, M4OSA_Double Cts, 945 M4ENCODER_FrameMode FrameMode) { 946 M4OSA_ERR err = M4NO_ERROR; 947 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 948 status_t result = OK; 949 MediaBuffer* outputBuffer = NULL; 950 951 LOGV("VideoEditorVideoEncoder_encode 0x%X %f %d", pInPlane, Cts, FrameMode); 952 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 953 954 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 955 if ( STARTED == pEncoderContext->mState ) { 956 pEncoderContext->mState = BUFFERING; 957 } 958 VIDEOEDITOR_CHECK( 959 (BUFFERING | READING) & pEncoderContext->mState, M4ERR_STATE); 960 961 pEncoderContext->mNbInputFrames++; 962 if ( 0 > pEncoderContext->mFirstInputCts ) { 963 pEncoderContext->mFirstInputCts = Cts; 964 } 965 pEncoderContext->mLastInputCts = Cts; 966 967 LOGV("VideoEditorVideoEncoder_encode 0x%X %d %f (%d)", pInPlane, FrameMode, 968 Cts, pEncoderContext->mLastCTS); 969 970 // Push the input buffer to the encoder source 971 err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, Cts, 972 M4OSA_FALSE); 973 VIDEOEDITOR_CHECK((M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err), err); 974 975 // Notify the source in case of EOS 976 if ( M4ENCODER_kLastFrame == FrameMode ) { 977 err = VideoEditorVideoEncoder_processInputBuffer( 978 pEncoderContext, 0, M4OSA_TRUE); 979 VIDEOEDITOR_CHECK((M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err), 980 err); 981 } 982 983 if ( BUFFERING == pEncoderContext->mState ) { 984 if ( M4WAR_SF_LOW_BUFFER == err ) { 985 // Insufficient prefetch, do not encode 986 err = M4NO_ERROR; 987 goto cleanUp; 988 } else { 989 // Prefetch is complete, start reading 990 pEncoderContext->mState = READING; 991 } 992 } 993 // Read 994 result = pEncoderContext->mEncoder->read(&outputBuffer, NULL); 995 if( OK != result ) { 996 LOGV("VideoEditorVideoEncoder_encode: encoder returns 0x%X", result); 997 } 998 999 if( ERROR_END_OF_STREAM == result ) { 1000 if( outputBuffer != NULL ) { 1001 LOGV("VideoEditorVideoEncoder_encode : EOS w/ buffer"); 1002 } 1003 VIDEOEDITOR_CHECK(0 == VIDEOEDITOR_MIN_BUFFER_NB, M4ERR_STATE); 1004 // No output provided here, just exit 1005 goto cleanUp; 1006 } 1007 VIDEOEDITOR_CHECK((OK == result) || (ERROR_END_OF_STREAM == result), 1008 M4ERR_STATE); 1009 1010 // Provide the encoded AU to the writer 1011 err = VideoEditorVideoEncoder_processOutputBuffer(pEncoderContext, 1012 outputBuffer); 1013 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 1014 1015cleanUp: 1016 if( M4NO_ERROR == err ) { 1017 LOGV("VideoEditorVideoEncoder_encode no error"); 1018 } else { 1019 LOGV("VideoEditorVideoEncoder_encode ERROR 0x%X", err); 1020 } 1021 LOGV("VideoEditorVideoEncoder_encode end"); 1022 return err; 1023} 1024 1025M4OSA_ERR VideoEditorVideoEncoder_start(M4ENCODER_Context pContext) { 1026 M4OSA_ERR err = M4NO_ERROR; 1027 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1028 status_t result = OK; 1029 1030 LOGV("VideoEditorVideoEncoder_start begin"); 1031 // Input parameters check 1032 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1033 1034 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1035 VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE); 1036 1037 pEncoderContext->mNbInputFrames = 0; 1038 pEncoderContext->mFirstInputCts = -1.0; 1039 pEncoderContext->mLastInputCts = -1.0; 1040 pEncoderContext->mNbOutputFrames = 0; 1041 pEncoderContext->mFirstOutputCts = -1; 1042 pEncoderContext->mLastOutputCts = -1; 1043 1044 result = pEncoderContext->mEncoder->start(); 1045 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 1046 1047 // Set the new state 1048 pEncoderContext->mState = STARTED; 1049 1050cleanUp: 1051 if ( M4NO_ERROR == err ) { 1052 LOGV("VideoEditorVideoEncoder_start no error"); 1053 } else { 1054 LOGV("VideoEditorVideoEncoder_start ERROR 0x%X", err); 1055 } 1056 LOGV("VideoEditorVideoEncoder_start end"); 1057 return err; 1058} 1059 1060M4OSA_ERR VideoEditorVideoEncoder_stop(M4ENCODER_Context pContext) { 1061 M4OSA_ERR err = M4NO_ERROR; 1062 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1063 MediaBuffer* outputBuffer = NULL; 1064 status_t result = OK; 1065 1066 LOGV("VideoEditorVideoEncoder_stop begin"); 1067 // Input parameters check 1068 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1069 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1070 1071 // Process the remaining buffers if necessary 1072 if ( (BUFFERING | READING) & pEncoderContext->mState ) { 1073 // Send EOS again just in case 1074 err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, 0, 1075 M4OSA_TRUE); 1076 VIDEOEDITOR_CHECK((M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err), 1077 err); 1078 while( OK == result ) { 1079 result = pEncoderContext->mEncoder->read(&outputBuffer, NULL); 1080 if ( OK == result ) { 1081 err = VideoEditorVideoEncoder_processOutputBuffer( 1082 pEncoderContext, outputBuffer); 1083 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 1084 } 1085 } 1086 pEncoderContext->mState = STARTED; 1087 } 1088 1089 // Stop the graph module if necessary 1090 if ( STARTED == pEncoderContext->mState ) { 1091 pEncoderContext->mEncoder->stop(); 1092 pEncoderContext->mState = OPENED; 1093 } 1094 1095 if ( pEncoderContext->mNbInputFrames != pEncoderContext->mNbInputFrames ) { 1096 LOGV("VideoEditorVideoEncoder_stop: some frames were not encoded %d %d", 1097 pEncoderContext->mNbInputFrames, pEncoderContext->mNbInputFrames); 1098 } 1099 1100cleanUp: 1101 if ( M4NO_ERROR == err ) { 1102 LOGV("VideoEditorVideoEncoder_stop no error"); 1103 } else { 1104 LOGV("VideoEditorVideoEncoder_stop ERROR 0x%X", err); 1105 } 1106 LOGV("VideoEditorVideoEncoder_stop end"); 1107 return err; 1108} 1109 1110M4OSA_ERR VideoEditorVideoEncoder_regulBitRate(M4ENCODER_Context pContext) { 1111 M4OSA_ERR err = M4NO_ERROR; 1112 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1113 1114 LOGV("VideoEditorVideoEncoder_regulBitRate begin"); 1115 // Input parameters check 1116 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1117 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1118 1119 LOGV("VideoEditorVideoEncoder_regulBitRate : THIS IS NOT IMPLEMENTED"); 1120 1121cleanUp: 1122 if ( M4NO_ERROR == err ) { 1123 LOGV("VideoEditorVideoEncoder_regulBitRate no error"); 1124 } else { 1125 LOGV("VideoEditorVideoEncoder_regulBitRate ERROR 0x%X", err); 1126 } 1127 LOGV("VideoEditorVideoEncoder_regulBitRate end"); 1128 return err; 1129} 1130 1131M4OSA_ERR VideoEditorVideoEncoder_setOption(M4ENCODER_Context pContext, 1132 M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) { 1133 M4OSA_ERR err = M4NO_ERROR; 1134 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1135 1136 LOGV("VideoEditorVideoEncoder_setOption start optionID 0x%X", optionID); 1137 // Input parameters check 1138 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1139 1140 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1141 1142 switch( optionID ) { 1143 case M4ENCODER_kOptionID_SetH264ProcessNALUfctsPtr: 1144 pEncoderContext->mH264NALUPostProcessFct = 1145 (H264MCS_ProcessEncodedNALU_fct*)optionValue; 1146 break; 1147 case M4ENCODER_kOptionID_H264ProcessNALUContext: 1148 pEncoderContext->mH264NALUPostProcessCtx = 1149 (M4OSA_Context)optionValue; 1150 break; 1151 default: 1152 LOGV("VideoEditorVideoEncoder_setOption: unsupported optionId 0x%X", 1153 optionID); 1154 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID); 1155 break; 1156 } 1157 1158cleanUp: 1159 if ( M4NO_ERROR == err ) { 1160 LOGV("VideoEditorVideoEncoder_setOption no error"); 1161 } else { 1162 LOGV("VideoEditorVideoEncoder_setOption ERROR 0x%X", err); 1163 } 1164 LOGV("VideoEditorVideoEncoder_setOption end"); 1165 return err; 1166} 1167 1168M4OSA_ERR VideoEditorVideoEncoder_getOption(M4ENCODER_Context pContext, 1169 M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) { 1170 M4OSA_ERR err = M4NO_ERROR; 1171 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1172 1173 LOGV("VideoEditorVideoEncoder_getOption begin optinId 0x%X", optionID); 1174 // Input parameters check 1175 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1176 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1177 1178 switch( optionID ) { 1179 case M4ENCODER_kOptionID_EncoderHeader: 1180 VIDEOEDITOR_CHECK( 1181 M4OSA_NULL != pEncoderContext->mHeader.pBuf, M4ERR_STATE); 1182 *(M4ENCODER_Header**)optionValue = &(pEncoderContext->mHeader); 1183 break; 1184 default: 1185 LOGV("VideoEditorVideoEncoder_getOption: unsupported optionId 0x%X", 1186 optionID); 1187 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID); 1188 break; 1189 } 1190 1191cleanUp: 1192 if ( M4NO_ERROR == err ) { 1193 LOGV("VideoEditorVideoEncoder_getOption no error"); 1194 } else { 1195 LOGV("VideoEditorVideoEncoder_getOption ERROR 0x%X", err); 1196 } 1197 return err; 1198} 1199 1200M4OSA_ERR VideoEditorVideoEncoder_getInterface(M4ENCODER_Format format, 1201 M4ENCODER_Format* pFormat, 1202 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1203 M4OSA_ERR err = M4NO_ERROR; 1204 1205 // Input parameters check 1206 VIDEOEDITOR_CHECK(M4OSA_NULL != pFormat, M4ERR_PARAMETER); 1207 VIDEOEDITOR_CHECK(M4OSA_NULL != pEncoderInterface, M4ERR_PARAMETER); 1208 1209 LOGV("VideoEditorVideoEncoder_getInterface begin 0x%x 0x%x %d", pFormat, 1210 pEncoderInterface, mode); 1211 1212 SAFE_MALLOC(*pEncoderInterface, M4ENCODER_GlobalInterface, 1, 1213 "VideoEditorVideoEncoder"); 1214 1215 *pFormat = format; 1216 1217 switch( format ) { 1218 case M4ENCODER_kH263: 1219 { 1220 (*pEncoderInterface)->pFctInit = 1221 VideoEditorVideoEncoder_init_H263; 1222 break; 1223 } 1224 case M4ENCODER_kMPEG4: 1225 { 1226 (*pEncoderInterface)->pFctInit = 1227 VideoEditorVideoEncoder_init_MPEG4; 1228 break; 1229 } 1230 case M4ENCODER_kH264: 1231 { 1232 (*pEncoderInterface)->pFctInit = 1233 VideoEditorVideoEncoder_init_H264; 1234 break; 1235 } 1236 default: 1237 LOGV("VideoEditorVideoEncoder_getInterface : unsupported format %d", 1238 format); 1239 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER); 1240 break; 1241 } 1242 (*pEncoderInterface)->pFctOpen = VideoEditorVideoEncoder_open; 1243 (*pEncoderInterface)->pFctStart = VideoEditorVideoEncoder_start; 1244 (*pEncoderInterface)->pFctStop = VideoEditorVideoEncoder_stop; 1245 (*pEncoderInterface)->pFctPause = M4OSA_NULL; 1246 (*pEncoderInterface)->pFctResume = M4OSA_NULL; 1247 (*pEncoderInterface)->pFctClose = VideoEditorVideoEncoder_close; 1248 (*pEncoderInterface)->pFctCleanup = VideoEditorVideoEncoder_cleanup; 1249 (*pEncoderInterface)->pFctRegulBitRate = 1250 VideoEditorVideoEncoder_regulBitRate; 1251 (*pEncoderInterface)->pFctEncode = VideoEditorVideoEncoder_encode; 1252 (*pEncoderInterface)->pFctSetOption = VideoEditorVideoEncoder_setOption; 1253 (*pEncoderInterface)->pFctGetOption = VideoEditorVideoEncoder_getOption; 1254 1255cleanUp: 1256 if( M4NO_ERROR == err ) { 1257 LOGV("VideoEditorVideoEncoder_getInterface no error"); 1258 } else { 1259 *pEncoderInterface = M4OSA_NULL; 1260 LOGV("VideoEditorVideoEncoder_getInterface ERROR 0x%X", err); 1261 } 1262 return err; 1263} 1264 1265extern "C" { 1266 1267M4OSA_ERR VideoEditorVideoEncoder_getInterface_H263(M4ENCODER_Format* pFormat, 1268 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1269 return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH263, pFormat, 1270 pEncoderInterface, mode); 1271} 1272 1273M4OSA_ERR VideoEditorVideoEncoder_getInterface_MPEG4(M4ENCODER_Format* pFormat, 1274 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1275 return VideoEditorVideoEncoder_getInterface(M4ENCODER_kMPEG4, pFormat, 1276 pEncoderInterface, mode); 1277} 1278 1279M4OSA_ERR VideoEditorVideoEncoder_getInterface_H264(M4ENCODER_Format* pFormat, 1280 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1281 return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH264, pFormat, 1282 pEncoderInterface, mode); 1283 1284} 1285 1286} // extern "C" 1287 1288} // namespace android 1289