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