avc_utils.cpp revision bfd41f33c77c66ead48ee378e4ea4b7bfa5fca1f
1/* 2 * Copyright (C) 2010 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#include "include/avc_utils.h" 18 19#include <media/stagefright/foundation/ABitReader.h> 20#include <media/stagefright/foundation/ADebug.h> 21#include <media/stagefright/MediaDefs.h> 22#include <media/stagefright/MediaErrors.h> 23#include <media/stagefright/MetaData.h> 24 25namespace android { 26 27unsigned parseUE(ABitReader *br) { 28 unsigned numZeroes = 0; 29 while (br->getBits(1) == 0) { 30 ++numZeroes; 31 } 32 33 unsigned x = br->getBits(numZeroes); 34 35 return x + (1u << numZeroes) - 1; 36} 37 38// Determine video dimensions from the sequence parameterset. 39void FindAVCDimensions( 40 const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height) { 41 ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1); 42 43 unsigned profile_idc = br.getBits(8); 44 br.skipBits(16); 45 parseUE(&br); // seq_parameter_set_id 46 47 unsigned chroma_format_idc = 1; // 4:2:0 chroma format 48 49 if (profile_idc == 100 || profile_idc == 110 50 || profile_idc == 122 || profile_idc == 244 51 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86) { 52 chroma_format_idc = parseUE(&br); 53 if (chroma_format_idc == 3) { 54 br.skipBits(1); // residual_colour_transform_flag 55 } 56 parseUE(&br); // bit_depth_luma_minus8 57 parseUE(&br); // bit_depth_chroma_minus8 58 br.skipBits(1); // qpprime_y_zero_transform_bypass_flag 59 CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag 60 } 61 62 parseUE(&br); // log2_max_frame_num_minus4 63 unsigned pic_order_cnt_type = parseUE(&br); 64 65 if (pic_order_cnt_type == 0) { 66 parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4 67 } else if (pic_order_cnt_type == 1) { 68 // offset_for_non_ref_pic, offset_for_top_to_bottom_field and 69 // offset_for_ref_frame are technically se(v), but since we are 70 // just skipping over them the midpoint does not matter. 71 72 br.getBits(1); // delta_pic_order_always_zero_flag 73 parseUE(&br); // offset_for_non_ref_pic 74 parseUE(&br); // offset_for_top_to_bottom_field 75 76 unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br); 77 for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) { 78 parseUE(&br); // offset_for_ref_frame 79 } 80 } 81 82 parseUE(&br); // num_ref_frames 83 br.getBits(1); // gaps_in_frame_num_value_allowed_flag 84 85 unsigned pic_width_in_mbs_minus1 = parseUE(&br); 86 unsigned pic_height_in_map_units_minus1 = parseUE(&br); 87 unsigned frame_mbs_only_flag = br.getBits(1); 88 89 *width = pic_width_in_mbs_minus1 * 16 + 16; 90 91 *height = (2 - frame_mbs_only_flag) 92 * (pic_height_in_map_units_minus1 * 16 + 16); 93 94 if (!frame_mbs_only_flag) { 95 br.getBits(1); // mb_adaptive_frame_field_flag 96 } 97 98 br.getBits(1); // direct_8x8_inference_flag 99 100 if (br.getBits(1)) { // frame_cropping_flag 101 unsigned frame_crop_left_offset = parseUE(&br); 102 unsigned frame_crop_right_offset = parseUE(&br); 103 unsigned frame_crop_top_offset = parseUE(&br); 104 unsigned frame_crop_bottom_offset = parseUE(&br); 105 106 unsigned cropUnitX, cropUnitY; 107 if (chroma_format_idc == 0 /* monochrome */) { 108 cropUnitX = 1; 109 cropUnitY = 2 - frame_mbs_only_flag; 110 } else { 111 unsigned subWidthC = (chroma_format_idc == 3) ? 1 : 2; 112 unsigned subHeightC = (chroma_format_idc == 1) ? 2 : 1; 113 114 cropUnitX = subWidthC; 115 cropUnitY = subHeightC * (2 - frame_mbs_only_flag); 116 } 117 118 LOGV("frame_crop = (%u, %u, %u, %u), cropUnitX = %u, cropUnitY = %u", 119 frame_crop_left_offset, frame_crop_right_offset, 120 frame_crop_top_offset, frame_crop_bottom_offset, 121 cropUnitX, cropUnitY); 122 123 *width -= 124 (frame_crop_left_offset + frame_crop_right_offset) * cropUnitX; 125 *height -= 126 (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY; 127 } 128} 129 130status_t getNextNALUnit( 131 const uint8_t **_data, size_t *_size, 132 const uint8_t **nalStart, size_t *nalSize, 133 bool startCodeFollows) { 134 const uint8_t *data = *_data; 135 size_t size = *_size; 136 137 *nalStart = NULL; 138 *nalSize = 0; 139 140 if (size == 0) { 141 return -EAGAIN; 142 } 143 144 // Skip any number of leading 0x00. 145 146 size_t offset = 0; 147 while (offset < size && data[offset] == 0x00) { 148 ++offset; 149 } 150 151 if (offset == size) { 152 return -EAGAIN; 153 } 154 155 // A valid startcode consists of at least two 0x00 bytes followed by 0x01. 156 157 if (offset < 2 || data[offset] != 0x01) { 158 return ERROR_MALFORMED; 159 } 160 161 ++offset; 162 163 size_t startOffset = offset; 164 165 for (;;) { 166 while (offset < size && data[offset] != 0x01) { 167 ++offset; 168 } 169 170 if (offset == size) { 171 if (startCodeFollows) { 172 offset = size + 2; 173 break; 174 } 175 176 return -EAGAIN; 177 } 178 179 if (data[offset - 1] == 0x00 && data[offset - 2] == 0x00) { 180 break; 181 } 182 183 ++offset; 184 } 185 186 size_t endOffset = offset - 2; 187 while (data[endOffset - 1] == 0x00) { 188 --endOffset; 189 } 190 191 *nalStart = &data[startOffset]; 192 *nalSize = endOffset - startOffset; 193 194 if (offset + 2 < size) { 195 *_data = &data[offset - 2]; 196 *_size = size - offset + 2; 197 } else { 198 *_data = NULL; 199 *_size = 0; 200 } 201 202 return OK; 203} 204 205static sp<ABuffer> FindNAL( 206 const uint8_t *data, size_t size, unsigned nalType, 207 size_t *stopOffset) { 208 const uint8_t *nalStart; 209 size_t nalSize; 210 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 211 if ((nalStart[0] & 0x1f) == nalType) { 212 sp<ABuffer> buffer = new ABuffer(nalSize); 213 memcpy(buffer->data(), nalStart, nalSize); 214 return buffer; 215 } 216 } 217 218 return NULL; 219} 220 221const char *AVCProfileToString(uint8_t profile) { 222 switch (profile) { 223 case kAVCProfileBaseline: 224 return "Baseline"; 225 case kAVCProfileMain: 226 return "Main"; 227 case kAVCProfileExtended: 228 return "Extended"; 229 case kAVCProfileHigh: 230 return "High"; 231 case kAVCProfileHigh10: 232 return "High 10"; 233 case kAVCProfileHigh422: 234 return "High 422"; 235 case kAVCProfileHigh444: 236 return "High 444"; 237 case kAVCProfileCAVLC444Intra: 238 return "CAVLC 444 Intra"; 239 default: return "Unknown"; 240 } 241} 242 243sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { 244 const uint8_t *data = accessUnit->data(); 245 size_t size = accessUnit->size(); 246 247 sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL); 248 if (seqParamSet == NULL) { 249 return NULL; 250 } 251 252 int32_t width, height; 253 FindAVCDimensions(seqParamSet, &width, &height); 254 255 size_t stopOffset; 256 sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); 257 CHECK(picParamSet != NULL); 258 259 size_t csdSize = 260 1 + 3 + 1 + 1 261 + 2 * 1 + seqParamSet->size() 262 + 1 + 2 * 1 + picParamSet->size(); 263 264 sp<ABuffer> csd = new ABuffer(csdSize); 265 uint8_t *out = csd->data(); 266 267 *out++ = 0x01; // configurationVersion 268 memcpy(out, seqParamSet->data() + 1, 3); // profile/level... 269 270 uint8_t profile = out[0]; 271 uint8_t level = out[2]; 272 273 out += 3; 274 *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes 275 *out++ = 0xe0 | 1; 276 277 *out++ = seqParamSet->size() >> 8; 278 *out++ = seqParamSet->size() & 0xff; 279 memcpy(out, seqParamSet->data(), seqParamSet->size()); 280 out += seqParamSet->size(); 281 282 *out++ = 1; 283 284 *out++ = picParamSet->size() >> 8; 285 *out++ = picParamSet->size() & 0xff; 286 memcpy(out, picParamSet->data(), picParamSet->size()); 287 288#if 0 289 LOGI("AVC seq param set"); 290 hexdump(seqParamSet->data(), seqParamSet->size()); 291#endif 292 293 sp<MetaData> meta = new MetaData; 294 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 295 296 meta->setData(kKeyAVCC, 0, csd->data(), csd->size()); 297 meta->setInt32(kKeyWidth, width); 298 meta->setInt32(kKeyHeight, height); 299 300 LOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", 301 width, height, AVCProfileToString(profile), level / 10, level % 10); 302 303 return meta; 304} 305 306bool IsIDR(const sp<ABuffer> &buffer) { 307 const uint8_t *data = buffer->data(); 308 size_t size = buffer->size(); 309 310 bool foundIDR = false; 311 312 const uint8_t *nalStart; 313 size_t nalSize; 314 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 315 CHECK_GT(nalSize, 0u); 316 317 unsigned nalType = nalStart[0] & 0x1f; 318 319 if (nalType == 5) { 320 foundIDR = true; 321 break; 322 } 323 } 324 325 return foundIDR; 326} 327 328} // namespace android 329 330