VideoEditorVideoEncoder.cpp revision 3b25fdc4a33b53cfcf67315c2d42ad699b8cefe2
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 memcpy((void *)pEncoderContext->mHeader.pBuf, 364 (void *)((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 { // Display the DSI 813 LOGV("VideoEditorVideoEncoder_processOutputBuffer DSI %d", 814 buffer->range_length()); 815 uint8_t* tmp = (uint8_t*)(buffer->data()); 816 for( uint32_t i=0; i<buffer->range_length(); i++ ) { 817 LOGV("DSI [%d] %.2X", i, tmp[i]); 818 } 819 } 820 821#ifndef VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION 822 VIDEOEDITOR_CHECK(M4OSA_NULL == pEncoderContext->mHeader.pBuf, 823 M4ERR_STATE); 824 if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) { 825 result = buildAVCCodecSpecificData( 826 (uint8_t**)(&(pEncoderContext->mHeader.pBuf)), 827 (size_t*)(&(pEncoderContext->mHeader.Size)), 828 (const uint8_t *)buffer->data() + buffer->range_offset(), 829 buffer->range_length(), 830 pEncoderContext->mEncoder->getFormat().get()); 831 } else { 832 pEncoderContext->mHeader.Size = 833 (M4OSA_UInt32)buffer->range_length(); 834 SAFE_MALLOC(pEncoderContext->mHeader.pBuf, M4OSA_Int8, 835 pEncoderContext->mHeader.Size, "Encoder header"); 836 memcpy((void *)pEncoderContext->mHeader.pBuf, 837 (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->range_offset()), 838 pEncoderContext->mHeader.Size); 839 } 840#endif /* VIDEOEDITOR_ENCODER_GET_DSI_AT_CREATION */ 841 } else { 842 // Check the CTS 843 VIDEOEDITOR_CHECK(buffer->meta_data()->findInt64(kKeyTime, &i64Tmp), 844 M4ERR_STATE); 845 846 pEncoderContext->mNbOutputFrames++; 847 if ( 0 > pEncoderContext->mFirstOutputCts ) { 848 pEncoderContext->mFirstOutputCts = i64Tmp; 849 } 850 pEncoderContext->mLastOutputCts = i64Tmp; 851 852 Cts = (M4OSA_Int32)(i64Tmp/1000); 853 LOGV("[TS_CHECK] VI/ENC WRITE frame %d @ %lld -> %d (last %d)", 854 pEncoderContext->mNbOutputFrames, i64Tmp, Cts, 855 pEncoderContext->mLastCTS); 856 if ( Cts < pEncoderContext->mLastCTS ) { 857 LOGV("VideoEncoder_processOutputBuffer WARNING : Cts is going " 858 "backwards %d < %d", Cts, pEncoderContext->mLastCTS); 859 goto cleanUp; 860 } 861 LOGV("VideoEditorVideoEncoder_processOutputBuffer : %d %d", 862 Cts, pEncoderContext->mLastCTS); 863 864 // Retrieve the AU container 865 err = pEncoderContext->mWriterDataInterface->pStartAU( 866 pEncoderContext->mWriterDataInterface->pWriterContext, 867 pEncoderContext->mAccessUnit->stream->streamID, 868 pEncoderContext->mAccessUnit); 869 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 870 871 // Format the AU 872 VIDEOEDITOR_CHECK( 873 buffer->range_length() <= pEncoderContext->mAccessUnit->size, 874 M4ERR_PARAMETER); 875 // Remove H264 AU start code 876 if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) { 877 if (!memcmp((const uint8_t *)buffer->data() + \ 878 buffer->range_offset(), "\x00\x00\x00\x01", 4) ) { 879 buffer->set_range(buffer->range_offset() + 4, 880 buffer->range_length() - 4); 881 } 882 } 883 884 if ( (M4ENCODER_kH264 == pEncoderContext->mFormat) && 885 (M4OSA_NULL != pEncoderContext->mH264NALUPostProcessFct) ) { 886 // H264 trimming case, NALU post processing is needed 887 M4OSA_Int32 outputSize = pEncoderContext->mAccessUnit->size; 888 err = pEncoderContext->mH264NALUPostProcessFct( 889 pEncoderContext->mH264NALUPostProcessCtx, 890 (M4OSA_UInt8*)buffer->data()+buffer->range_offset(), 891 buffer->range_length(), 892 (M4OSA_UInt8*)pEncoderContext->mAccessUnit->dataAddress, 893 &outputSize); 894 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 895 pEncoderContext->mAccessUnit->size = (M4OSA_UInt32)outputSize; 896 } else { 897 // The AU can just be copied 898 memcpy((void *)pEncoderContext->mAccessUnit->\ 899 dataAddress, (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->\ 900 range_offset()), buffer->range_length()); 901 pEncoderContext->mAccessUnit->size = 902 (M4OSA_UInt32)buffer->range_length(); 903 } 904 905 if ( buffer->meta_data()->findInt32(kKeyIsSyncFrame,&i32Tmp) && i32Tmp){ 906 pEncoderContext->mAccessUnit->attribute = AU_RAP; 907 } else { 908 pEncoderContext->mAccessUnit->attribute = AU_P_Frame; 909 } 910 pEncoderContext->mLastCTS = Cts; 911 pEncoderContext->mAccessUnit->CTS = Cts; 912 pEncoderContext->mAccessUnit->DTS = Cts; 913 914 LOGV("VideoEditorVideoEncoder_processOutputBuffer: AU @ 0x%X 0x%X %d %d", 915 pEncoderContext->mAccessUnit->dataAddress, 916 *pEncoderContext->mAccessUnit->dataAddress, 917 pEncoderContext->mAccessUnit->size, 918 pEncoderContext->mAccessUnit->CTS); 919 920 // Write the AU 921 err = pEncoderContext->mWriterDataInterface->pProcessAU( 922 pEncoderContext->mWriterDataInterface->pWriterContext, 923 pEncoderContext->mAccessUnit->stream->streamID, 924 pEncoderContext->mAccessUnit); 925 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 926 } 927 928cleanUp: 929 buffer->release(); 930 if( M4NO_ERROR == err ) { 931 LOGV("VideoEditorVideoEncoder_processOutputBuffer no error"); 932 } else { 933 SAFE_FREE(pEncoderContext->mHeader.pBuf); 934 pEncoderContext->mHeader.Size = 0; 935 LOGV("VideoEditorVideoEncoder_processOutputBuffer ERROR 0x%X", err); 936 } 937 LOGV("VideoEditorVideoEncoder_processOutputBuffer end"); 938 return err; 939} 940 941M4OSA_ERR VideoEditorVideoEncoder_encode(M4ENCODER_Context pContext, 942 M4VIFI_ImagePlane* pInPlane, M4OSA_Double Cts, 943 M4ENCODER_FrameMode FrameMode) { 944 M4OSA_ERR err = M4NO_ERROR; 945 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 946 status_t result = OK; 947 MediaBuffer* outputBuffer = NULL; 948 949 LOGV("VideoEditorVideoEncoder_encode 0x%X %f %d", pInPlane, Cts, FrameMode); 950 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 951 952 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 953 if ( STARTED == pEncoderContext->mState ) { 954 pEncoderContext->mState = BUFFERING; 955 } 956 VIDEOEDITOR_CHECK( 957 (BUFFERING | READING) & pEncoderContext->mState, M4ERR_STATE); 958 959 pEncoderContext->mNbInputFrames++; 960 if ( 0 > pEncoderContext->mFirstInputCts ) { 961 pEncoderContext->mFirstInputCts = Cts; 962 } 963 pEncoderContext->mLastInputCts = Cts; 964 965 LOGV("VideoEditorVideoEncoder_encode 0x%X %d %f (%d)", pInPlane, FrameMode, 966 Cts, pEncoderContext->mLastCTS); 967 968 // Push the input buffer to the encoder source 969 err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, Cts, 970 M4OSA_FALSE); 971 VIDEOEDITOR_CHECK((M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err), err); 972 973 // Notify the source in case of EOS 974 if ( M4ENCODER_kLastFrame == FrameMode ) { 975 err = VideoEditorVideoEncoder_processInputBuffer( 976 pEncoderContext, 0, M4OSA_TRUE); 977 VIDEOEDITOR_CHECK((M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err), 978 err); 979 } 980 981 if ( BUFFERING == pEncoderContext->mState ) { 982 if ( M4WAR_SF_LOW_BUFFER == err ) { 983 // Insufficient prefetch, do not encode 984 err = M4NO_ERROR; 985 goto cleanUp; 986 } else { 987 // Prefetch is complete, start reading 988 pEncoderContext->mState = READING; 989 } 990 } 991 // Read 992 result = pEncoderContext->mEncoder->read(&outputBuffer, NULL); 993 if( OK != result ) { 994 LOGV("VideoEditorVideoEncoder_encode: encoder returns 0x%X", result); 995 } 996 997 if( ERROR_END_OF_STREAM == result ) { 998 if( outputBuffer != NULL ) { 999 LOGV("VideoEditorVideoEncoder_encode : EOS w/ buffer"); 1000 } 1001 VIDEOEDITOR_CHECK(0 == VIDEOEDITOR_MIN_BUFFER_NB, M4ERR_STATE); 1002 // No output provided here, just exit 1003 goto cleanUp; 1004 } 1005 VIDEOEDITOR_CHECK((OK == result) || (ERROR_END_OF_STREAM == result), 1006 M4ERR_STATE); 1007 1008 // Provide the encoded AU to the writer 1009 err = VideoEditorVideoEncoder_processOutputBuffer(pEncoderContext, 1010 outputBuffer); 1011 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 1012 1013cleanUp: 1014 if( M4NO_ERROR == err ) { 1015 LOGV("VideoEditorVideoEncoder_encode no error"); 1016 } else { 1017 LOGV("VideoEditorVideoEncoder_encode ERROR 0x%X", err); 1018 } 1019 LOGV("VideoEditorVideoEncoder_encode end"); 1020 return err; 1021} 1022 1023M4OSA_ERR VideoEditorVideoEncoder_start(M4ENCODER_Context pContext) { 1024 M4OSA_ERR err = M4NO_ERROR; 1025 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1026 status_t result = OK; 1027 1028 LOGV("VideoEditorVideoEncoder_start begin"); 1029 // Input parameters check 1030 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1031 1032 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1033 VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE); 1034 1035 pEncoderContext->mNbInputFrames = 0; 1036 pEncoderContext->mFirstInputCts = -1.0; 1037 pEncoderContext->mLastInputCts = -1.0; 1038 pEncoderContext->mNbOutputFrames = 0; 1039 pEncoderContext->mFirstOutputCts = -1; 1040 pEncoderContext->mLastOutputCts = -1; 1041 1042 result = pEncoderContext->mEncoder->start(); 1043 VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE); 1044 1045 // Set the new state 1046 pEncoderContext->mState = STARTED; 1047 1048cleanUp: 1049 if ( M4NO_ERROR == err ) { 1050 LOGV("VideoEditorVideoEncoder_start no error"); 1051 } else { 1052 LOGV("VideoEditorVideoEncoder_start ERROR 0x%X", err); 1053 } 1054 LOGV("VideoEditorVideoEncoder_start end"); 1055 return err; 1056} 1057 1058M4OSA_ERR VideoEditorVideoEncoder_stop(M4ENCODER_Context pContext) { 1059 M4OSA_ERR err = M4NO_ERROR; 1060 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1061 MediaBuffer* outputBuffer = NULL; 1062 status_t result = OK; 1063 1064 LOGV("VideoEditorVideoEncoder_stop begin"); 1065 // Input parameters check 1066 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1067 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1068 1069 // Process the remaining buffers if necessary 1070 if ( (BUFFERING | READING) & pEncoderContext->mState ) { 1071 // Send EOS again just in case 1072 err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, 0, 1073 M4OSA_TRUE); 1074 VIDEOEDITOR_CHECK((M4NO_ERROR == err) || (M4WAR_SF_LOW_BUFFER == err), 1075 err); 1076 while( OK == result ) { 1077 result = pEncoderContext->mEncoder->read(&outputBuffer, NULL); 1078 if ( OK == result ) { 1079 err = VideoEditorVideoEncoder_processOutputBuffer( 1080 pEncoderContext, outputBuffer); 1081 VIDEOEDITOR_CHECK(M4NO_ERROR == err, err); 1082 } 1083 } 1084 pEncoderContext->mState = STARTED; 1085 } 1086 1087 // Stop the graph module if necessary 1088 if ( STARTED == pEncoderContext->mState ) { 1089 pEncoderContext->mEncoder->stop(); 1090 pEncoderContext->mState = OPENED; 1091 } 1092 1093 if ( pEncoderContext->mNbInputFrames != pEncoderContext->mNbInputFrames ) { 1094 LOGV("VideoEditorVideoEncoder_stop: some frames were not encoded %d %d", 1095 pEncoderContext->mNbInputFrames, pEncoderContext->mNbInputFrames); 1096 } 1097 1098cleanUp: 1099 if ( M4NO_ERROR == err ) { 1100 LOGV("VideoEditorVideoEncoder_stop no error"); 1101 } else { 1102 LOGV("VideoEditorVideoEncoder_stop ERROR 0x%X", err); 1103 } 1104 LOGV("VideoEditorVideoEncoder_stop end"); 1105 return err; 1106} 1107 1108M4OSA_ERR VideoEditorVideoEncoder_regulBitRate(M4ENCODER_Context pContext) { 1109 M4OSA_ERR err = M4NO_ERROR; 1110 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1111 1112 LOGV("VideoEditorVideoEncoder_regulBitRate begin"); 1113 // Input parameters check 1114 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1115 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1116 1117 LOGV("VideoEditorVideoEncoder_regulBitRate : THIS IS NOT IMPLEMENTED"); 1118 1119cleanUp: 1120 if ( M4NO_ERROR == err ) { 1121 LOGV("VideoEditorVideoEncoder_regulBitRate no error"); 1122 } else { 1123 LOGV("VideoEditorVideoEncoder_regulBitRate ERROR 0x%X", err); 1124 } 1125 LOGV("VideoEditorVideoEncoder_regulBitRate end"); 1126 return err; 1127} 1128 1129M4OSA_ERR VideoEditorVideoEncoder_setOption(M4ENCODER_Context pContext, 1130 M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) { 1131 M4OSA_ERR err = M4NO_ERROR; 1132 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1133 1134 LOGV("VideoEditorVideoEncoder_setOption start optionID 0x%X", optionID); 1135 // Input parameters check 1136 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1137 1138 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1139 1140 switch( optionID ) { 1141 case M4ENCODER_kOptionID_SetH264ProcessNALUfctsPtr: 1142 pEncoderContext->mH264NALUPostProcessFct = 1143 (H264MCS_ProcessEncodedNALU_fct*)optionValue; 1144 break; 1145 case M4ENCODER_kOptionID_H264ProcessNALUContext: 1146 pEncoderContext->mH264NALUPostProcessCtx = 1147 (M4OSA_Context)optionValue; 1148 break; 1149 default: 1150 LOGV("VideoEditorVideoEncoder_setOption: unsupported optionId 0x%X", 1151 optionID); 1152 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID); 1153 break; 1154 } 1155 1156cleanUp: 1157 if ( M4NO_ERROR == err ) { 1158 LOGV("VideoEditorVideoEncoder_setOption no error"); 1159 } else { 1160 LOGV("VideoEditorVideoEncoder_setOption ERROR 0x%X", err); 1161 } 1162 LOGV("VideoEditorVideoEncoder_setOption end"); 1163 return err; 1164} 1165 1166M4OSA_ERR VideoEditorVideoEncoder_getOption(M4ENCODER_Context pContext, 1167 M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) { 1168 M4OSA_ERR err = M4NO_ERROR; 1169 VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL; 1170 1171 LOGV("VideoEditorVideoEncoder_getOption begin optinId 0x%X", optionID); 1172 // Input parameters check 1173 VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER); 1174 pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext; 1175 1176 switch( optionID ) { 1177 case M4ENCODER_kOptionID_EncoderHeader: 1178 VIDEOEDITOR_CHECK( 1179 M4OSA_NULL != pEncoderContext->mHeader.pBuf, M4ERR_STATE); 1180 *(M4ENCODER_Header**)optionValue = &(pEncoderContext->mHeader); 1181 break; 1182 default: 1183 LOGV("VideoEditorVideoEncoder_getOption: unsupported optionId 0x%X", 1184 optionID); 1185 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID); 1186 break; 1187 } 1188 1189cleanUp: 1190 if ( M4NO_ERROR == err ) { 1191 LOGV("VideoEditorVideoEncoder_getOption no error"); 1192 } else { 1193 LOGV("VideoEditorVideoEncoder_getOption ERROR 0x%X", err); 1194 } 1195 return err; 1196} 1197 1198M4OSA_ERR VideoEditorVideoEncoder_getInterface(M4ENCODER_Format format, 1199 M4ENCODER_Format* pFormat, 1200 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1201 M4OSA_ERR err = M4NO_ERROR; 1202 1203 // Input parameters check 1204 VIDEOEDITOR_CHECK(M4OSA_NULL != pFormat, M4ERR_PARAMETER); 1205 VIDEOEDITOR_CHECK(M4OSA_NULL != pEncoderInterface, M4ERR_PARAMETER); 1206 1207 LOGV("VideoEditorVideoEncoder_getInterface begin 0x%x 0x%x %d", pFormat, 1208 pEncoderInterface, mode); 1209 1210 SAFE_MALLOC(*pEncoderInterface, M4ENCODER_GlobalInterface, 1, 1211 "VideoEditorVideoEncoder"); 1212 1213 *pFormat = format; 1214 1215 switch( format ) { 1216 case M4ENCODER_kH263: 1217 { 1218 (*pEncoderInterface)->pFctInit = 1219 VideoEditorVideoEncoder_init_H263; 1220 break; 1221 } 1222 case M4ENCODER_kMPEG4: 1223 { 1224 (*pEncoderInterface)->pFctInit = 1225 VideoEditorVideoEncoder_init_MPEG4; 1226 break; 1227 } 1228 case M4ENCODER_kH264: 1229 { 1230 (*pEncoderInterface)->pFctInit = 1231 VideoEditorVideoEncoder_init_H264; 1232 break; 1233 } 1234 default: 1235 LOGV("VideoEditorVideoEncoder_getInterface : unsupported format %d", 1236 format); 1237 VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER); 1238 break; 1239 } 1240 (*pEncoderInterface)->pFctOpen = VideoEditorVideoEncoder_open; 1241 (*pEncoderInterface)->pFctStart = VideoEditorVideoEncoder_start; 1242 (*pEncoderInterface)->pFctStop = VideoEditorVideoEncoder_stop; 1243 (*pEncoderInterface)->pFctPause = M4OSA_NULL; 1244 (*pEncoderInterface)->pFctResume = M4OSA_NULL; 1245 (*pEncoderInterface)->pFctClose = VideoEditorVideoEncoder_close; 1246 (*pEncoderInterface)->pFctCleanup = VideoEditorVideoEncoder_cleanup; 1247 (*pEncoderInterface)->pFctRegulBitRate = 1248 VideoEditorVideoEncoder_regulBitRate; 1249 (*pEncoderInterface)->pFctEncode = VideoEditorVideoEncoder_encode; 1250 (*pEncoderInterface)->pFctSetOption = VideoEditorVideoEncoder_setOption; 1251 (*pEncoderInterface)->pFctGetOption = VideoEditorVideoEncoder_getOption; 1252 1253cleanUp: 1254 if( M4NO_ERROR == err ) { 1255 LOGV("VideoEditorVideoEncoder_getInterface no error"); 1256 } else { 1257 *pEncoderInterface = M4OSA_NULL; 1258 LOGV("VideoEditorVideoEncoder_getInterface ERROR 0x%X", err); 1259 } 1260 return err; 1261} 1262 1263extern "C" { 1264 1265M4OSA_ERR VideoEditorVideoEncoder_getInterface_H263(M4ENCODER_Format* pFormat, 1266 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1267 return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH263, pFormat, 1268 pEncoderInterface, mode); 1269} 1270 1271M4OSA_ERR VideoEditorVideoEncoder_getInterface_MPEG4(M4ENCODER_Format* pFormat, 1272 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1273 return VideoEditorVideoEncoder_getInterface(M4ENCODER_kMPEG4, pFormat, 1274 pEncoderInterface, mode); 1275} 1276 1277M4OSA_ERR VideoEditorVideoEncoder_getInterface_H264(M4ENCODER_Format* pFormat, 1278 M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){ 1279 return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH264, pFormat, 1280 pEncoderInterface, mode); 1281 1282} 1283 1284} // extern "C" 1285 1286} // namespace android 1287