1 /* 2 * Copyright (c) 2009-2011 Intel Corporation. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <string.h> 18 #include <stdlib.h> 19 20 #include "VideoEncoderLog.h" 21 #include "VideoEncoderMP4.h" 22 #include <va/va_tpi.h> 23 24 VideoEncoderMP4::VideoEncoderMP4() 25 :mProfileLevelIndication(3) 26 ,mFixedVOPTimeIncrement(0) { 27 mComParams.profile = (VAProfile)PROFILE_MPEG4SIMPLE; 28 mAutoReferenceSurfaceNum = 2; 29 } 30 31 Encode_Status VideoEncoderMP4::getHeaderPos( 32 uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize) { 33 34 uint32_t bytesLeft = bufSize; 35 36 *headerSize = 0; 37 CHECK_NULL_RETURN_IFFAIL(inBuffer); 38 39 if (bufSize < 4) { 40 //bufSize shoule not < 4 41 LOG_E("Buffer size too small\n"); 42 return ENCODE_FAIL; 43 } 44 45 while (bytesLeft > 4 && 46 (memcmp("\x00\x00\x01\xB6", &inBuffer[bufSize - bytesLeft], 4) && 47 memcmp("\x00\x00\x01\xB3", &inBuffer[bufSize - bytesLeft], 4))) { 48 --bytesLeft; 49 } 50 51 if (bytesLeft <= 4) { 52 LOG_E("NO header found\n"); 53 *headerSize = 0; // 54 } else { 55 *headerSize = bufSize - bytesLeft; 56 } 57 58 return ENCODE_SUCCESS; 59 } 60 61 Encode_Status VideoEncoderMP4::outputConfigData( 62 VideoEncOutputBuffer *outBuffer) { 63 64 Encode_Status ret = ENCODE_SUCCESS; 65 uint32_t headerSize = 0; 66 67 ret = getHeaderPos((uint8_t *)mCurSegment->buf + mOffsetInSeg, 68 mCurSegment->size - mOffsetInSeg, &headerSize); 69 CHECK_ENCODE_STATUS_RETURN("getHeaderPos"); 70 if (headerSize == 0) { 71 outBuffer->dataSize = 0; 72 mCurSegment = NULL; 73 return ENCODE_NO_REQUEST_DATA; 74 } 75 76 if (headerSize <= outBuffer->bufferSize) { 77 memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, headerSize); 78 mTotalSizeCopied += headerSize; 79 mOffsetInSeg += headerSize; 80 outBuffer->dataSize = headerSize; 81 outBuffer->remainingSize = 0; 82 outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME; 83 outBuffer->flag |= ENCODE_BUFFERFLAG_CODECCONFIG; 84 outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME; 85 } else { 86 // we need a big enough buffer, otherwise we won't output anything 87 outBuffer->dataSize = 0; 88 outBuffer->remainingSize = headerSize; 89 outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID; 90 LOG_E("Buffer size too small\n"); 91 return ENCODE_BUFFER_TOO_SMALL; 92 } 93 94 return ret; 95 } 96 97 Encode_Status VideoEncoderMP4::getExtFormatOutput(VideoEncOutputBuffer *outBuffer) { 98 99 Encode_Status ret = ENCODE_SUCCESS; 100 101 LOG_V("Begin\n"); 102 CHECK_NULL_RETURN_IFFAIL(outBuffer); 103 104 switch (outBuffer->format) { 105 case OUTPUT_CODEC_DATA: { 106 // Output the codec config data 107 ret = outputConfigData(outBuffer); 108 CHECK_ENCODE_STATUS_CLEANUP("outputCodecData"); 109 break; 110 } 111 default: 112 LOG_E("Invalid buffer mode for MPEG-4:2\n"); 113 ret = ENCODE_FAIL; 114 break; 115 } 116 117 LOG_I("out size is = %d\n", outBuffer->dataSize); 118 119 120 CLEAN_UP: 121 122 LOG_V("End\n"); 123 return ret; 124 } 125 126 Encode_Status VideoEncoderMP4::renderSequenceParams(EncodeTask *) { 127 128 VAStatus vaStatus = VA_STATUS_SUCCESS; 129 VAEncSequenceParameterBufferMPEG4 mp4SequenceParams = VAEncSequenceParameterBufferMPEG4(); 130 131 uint32_t frameRateNum = mComParams.frameRate.frameRateNum; 132 uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom; 133 134 LOG_V( "Begin\n\n"); 135 // set up the sequence params for HW 136 mp4SequenceParams.profile_and_level_indication = mProfileLevelIndication; 137 mp4SequenceParams.video_object_layer_width= mComParams.resolution.width; 138 mp4SequenceParams.video_object_layer_height= mComParams.resolution.height; 139 mp4SequenceParams.vop_time_increment_resolution = 140 (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom; 141 mp4SequenceParams.fixed_vop_time_increment= mFixedVOPTimeIncrement; 142 mp4SequenceParams.bits_per_second= mComParams.rcParams.bitRate; 143 mp4SequenceParams.frame_rate = 144 (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom; 145 mp4SequenceParams.initial_qp = mComParams.rcParams.initQP; 146 mp4SequenceParams.min_qp = mComParams.rcParams.minQP; 147 mp4SequenceParams.intra_period = mComParams.intraPeriod; 148 //mpeg4_seq_param.fixed_vop_rate = 30; 149 150 LOG_V("===mpeg4 sequence params===\n"); 151 LOG_I("profile_and_level_indication = %d\n", (uint32_t)mp4SequenceParams.profile_and_level_indication); 152 LOG_I("intra_period = %d\n", mp4SequenceParams.intra_period); 153 LOG_I("video_object_layer_width = %d\n", mp4SequenceParams.video_object_layer_width); 154 LOG_I("video_object_layer_height = %d\n", mp4SequenceParams.video_object_layer_height); 155 LOG_I("vop_time_increment_resolution = %d\n", mp4SequenceParams.vop_time_increment_resolution); 156 LOG_I("fixed_vop_rate = %d\n", mp4SequenceParams.fixed_vop_rate); 157 LOG_I("fixed_vop_time_increment = %d\n", mp4SequenceParams.fixed_vop_time_increment); 158 LOG_I("bitrate = %d\n", mp4SequenceParams.bits_per_second); 159 LOG_I("frame_rate = %d\n", mp4SequenceParams.frame_rate); 160 LOG_I("initial_qp = %d\n", mp4SequenceParams.initial_qp); 161 LOG_I("min_qp = %d\n", mp4SequenceParams.min_qp); 162 LOG_I("intra_period = %d\n\n", mp4SequenceParams.intra_period); 163 164 vaStatus = vaCreateBuffer( 165 mVADisplay, mVAContext, 166 VAEncSequenceParameterBufferType, 167 sizeof(mp4SequenceParams), 168 1, &mp4SequenceParams, 169 &mSeqParamBuf); 170 CHECK_VA_STATUS_RETURN("vaCreateBuffer"); 171 172 vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1); 173 CHECK_VA_STATUS_RETURN("vaRenderPicture"); 174 175 LOG_V( "end\n"); 176 return ENCODE_SUCCESS; 177 } 178 179 Encode_Status VideoEncoderMP4::renderPictureParams(EncodeTask *task) { 180 181 VAStatus vaStatus = VA_STATUS_SUCCESS; 182 VAEncPictureParameterBufferMPEG4 mpeg4_pic_param = VAEncPictureParameterBufferMPEG4(); 183 LOG_V( "Begin\n\n"); 184 // set picture params for HW 185 if(mAutoReference == false){ 186 mpeg4_pic_param.reference_picture = task->ref_surface; 187 mpeg4_pic_param.reconstructed_picture = task->rec_surface; 188 }else { 189 mpeg4_pic_param.reference_picture = mAutoRefSurfaces[0]; 190 mpeg4_pic_param.reconstructed_picture = mAutoRefSurfaces[1]; 191 } 192 193 mpeg4_pic_param.coded_buf = task->coded_buffer; 194 mpeg4_pic_param.picture_width = mComParams.resolution.width; 195 mpeg4_pic_param.picture_height = mComParams.resolution.height; 196 mpeg4_pic_param.vop_time_increment= mFrameNum; 197 mpeg4_pic_param.picture_type = (task->type == FTYPE_I) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive; 198 199 LOG_V("======mpeg4 picture params======\n"); 200 LOG_V("reference_picture = 0x%08x\n", mpeg4_pic_param.reference_picture); 201 LOG_V("reconstructed_picture = 0x%08x\n", mpeg4_pic_param.reconstructed_picture); 202 LOG_V("coded_buf = 0x%08x\n", mpeg4_pic_param.coded_buf); 203 // LOG_I("coded_buf_index = %d\n", mCodedBufIndex); 204 LOG_V("picture_width = %d\n", mpeg4_pic_param.picture_width); 205 LOG_V("picture_height = %d\n", mpeg4_pic_param.picture_height); 206 LOG_V("vop_time_increment = %d\n", mpeg4_pic_param.vop_time_increment); 207 LOG_V("picture_type = %d\n\n", mpeg4_pic_param.picture_type); 208 209 vaStatus = vaCreateBuffer( 210 mVADisplay, mVAContext, 211 VAEncPictureParameterBufferType, 212 sizeof(mpeg4_pic_param), 213 1,&mpeg4_pic_param, 214 &mPicParamBuf); 215 CHECK_VA_STATUS_RETURN("vaCreateBuffer"); 216 217 vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1); 218 CHECK_VA_STATUS_RETURN("vaRenderPicture"); 219 220 return ENCODE_SUCCESS; 221 } 222 223 224 Encode_Status VideoEncoderMP4::renderSliceParams(EncodeTask *task) { 225 226 VAStatus vaStatus = VA_STATUS_SUCCESS; 227 uint32_t sliceHeight; 228 uint32_t sliceHeightInMB; 229 230 VAEncSliceParameterBuffer sliceParams; 231 232 LOG_V( "Begin\n\n"); 233 234 sliceHeight = mComParams.resolution.height; 235 sliceHeight += 15; 236 sliceHeight &= (~15); 237 sliceHeightInMB = sliceHeight / 16; 238 239 sliceParams.start_row_number = 0; 240 sliceParams.slice_height = sliceHeightInMB; 241 sliceParams.slice_flags.bits.is_intra = (task->type == FTYPE_I)?1:0; 242 sliceParams.slice_flags.bits.disable_deblocking_filter_idc = 0; 243 244 LOG_V("======mpeg4 slice params======\n"); 245 LOG_I( "start_row_number = %d\n", (int) sliceParams.start_row_number); 246 LOG_I( "sliceHeightInMB = %d\n", (int) sliceParams.slice_height); 247 LOG_I( "is_intra = %d\n", (int) sliceParams.slice_flags.bits.is_intra); 248 249 vaStatus = vaCreateBuffer( 250 mVADisplay, mVAContext, 251 VAEncSliceParameterBufferType, 252 sizeof(VAEncSliceParameterBuffer), 253 1, &sliceParams, 254 &mSliceParamBuf); 255 CHECK_VA_STATUS_RETURN("vaCreateBuffer"); 256 257 vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSliceParamBuf, 1); 258 CHECK_VA_STATUS_RETURN("vaRenderPicture"); 259 260 LOG_V( "end\n"); 261 return ENCODE_SUCCESS; 262 } 263 264 Encode_Status VideoEncoderMP4::sendEncodeCommand(EncodeTask *task) { 265 Encode_Status ret = ENCODE_SUCCESS; 266 LOG_V( "Begin\n"); 267 268 if (mFrameNum == 0) { 269 ret = renderSequenceParams(task); 270 CHECK_ENCODE_STATUS_RETURN("renderSequenceParams"); 271 } 272 273 ret = renderPictureParams(task); 274 CHECK_ENCODE_STATUS_RETURN("renderPictureParams"); 275 276 ret = renderSliceParams(task); 277 CHECK_ENCODE_STATUS_RETURN("renderPictureParams"); 278 279 LOG_V( "End\n"); 280 return ENCODE_SUCCESS; 281 } 282