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
VideoEncoderMP4()24 VideoEncoderMP4::VideoEncoderMP4()
25 :mProfileLevelIndication(3)
26 ,mFixedVOPTimeIncrement(0) {
27 mComParams.profile = (VAProfile)PROFILE_MPEG4SIMPLE;
28 mAutoReferenceSurfaceNum = 2;
29 }
30
getHeaderPos(uint8_t * inBuffer,uint32_t bufSize,uint32_t * headerSize)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
outputConfigData(VideoEncOutputBuffer * outBuffer)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
getExtFormatOutput(VideoEncOutputBuffer * outBuffer)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
renderSequenceParams(EncodeTask *)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
renderPictureParams(EncodeTask * task)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
renderSliceParams(EncodeTask * task)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
sendEncodeCommand(EncodeTask * task)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