// H.264 bitstream without start codes. sp<MetaData> setAVCFormat(AVCodecContext *avctx) { ALOGV("AVC"); CHECK_EQ(avctx->codec_id, AV_CODEC_ID_H264); CHECK_GT(avctx->extradata_size, 0); CHECK_EQ(avctx->extradata[0], 1); //configurationVersion if (avctx->width == 0 || avctx->height == 0) { int32_t width, height; sp<ABuffer> seqParamSet = new ABuffer(avctx->extradata_size - 8); memcpy(seqParamSet->data(), avctx->extradata + 8, avctx->extradata_size - 8); FindAVCDimensions(seqParamSet, &width, &height); avctx->width = width; avctx->height = height; } sp<MetaData> meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); meta->setData(kKeyAVCC, kTypeAVCC, avctx->extradata, avctx->extradata_size); return meta; }
sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { const uint8_t *data = accessUnit->data(); size_t size = accessUnit->size(); sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL); if (seqParamSet == NULL) { return NULL; } int32_t width, height; FindAVCDimensions(seqParamSet, &width, &height); size_t stopOffset; sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); CHECK(picParamSet != NULL); size_t csdSize = 1 + 3 + 1 + 1 + 2 * 1 + seqParamSet->size() + 1 + 2 * 1 + picParamSet->size(); sp<ABuffer> csd = new ABuffer(csdSize); uint8_t *out = csd->data(); *out++ = 0x01; // configurationVersion memcpy(out, seqParamSet->data() + 1, 3); // profile/level... uint8_t profile = out[0]; uint8_t level = out[2]; out += 3; *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes *out++ = 0xe0 | 1; *out++ = seqParamSet->size() >> 8; *out++ = seqParamSet->size() & 0xff; memcpy(out, seqParamSet->data(), seqParamSet->size()); out += seqParamSet->size(); *out++ = 1; *out++ = picParamSet->size() >> 8; *out++ = picParamSet->size() & 0xff; memcpy(out, picParamSet->data(), picParamSet->size()); #if 0 LOGI("AVC seq param set"); hexdump(seqParamSet->data(), seqParamSet->size()); #endif sp<MetaData> meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size()); meta->setInt32(kKeyWidth, width); meta->setInt32(kKeyHeight, height); LOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", width, height, AVCProfileToString(profile), level / 10, level % 10); return meta; }
sp<ABuffer> MakeAVCCodecSpecificData( const sp<ABuffer> &accessUnit, int32_t *width, int32_t *height, int32_t *sarWidth, int32_t *sarHeight) { const uint8_t *data = accessUnit->data(); size_t size = accessUnit->size(); sp<ABuffer> seqParamSet = FindNAL(data, size, 7); if (seqParamSet == NULL) { return NULL; } FindAVCDimensions( seqParamSet, width, height, sarWidth, sarHeight); sp<ABuffer> picParamSet = FindNAL(data, size, 8); CHECK(picParamSet != NULL); size_t csdSize = 1 + 3 + 1 + 1 + 2 * 1 + seqParamSet->size() + 1 + 2 * 1 + picParamSet->size(); sp<ABuffer> csd = new ABuffer(csdSize); uint8_t *out = csd->data(); *out++ = 0x01; // configurationVersion memcpy(out, seqParamSet->data() + 1, 3); // profile/level... uint8_t profile = out[0]; uint8_t level = out[2]; out += 3; *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes *out++ = 0xe0 | 1; *out++ = seqParamSet->size() >> 8; *out++ = seqParamSet->size() & 0xff; memcpy(out, seqParamSet->data(), seqParamSet->size()); out += seqParamSet->size(); *out++ = 1; *out++ = picParamSet->size() >> 8; *out++ = picParamSet->size() & 0xff; memcpy(out, picParamSet->data(), picParamSet->size()); #if 0 ALOGI("AVC seq param set"); hexdump(seqParamSet->data(), seqParamSet->size()); #endif if (sarWidth != nullptr && sarHeight != nullptr) { if ((*sarWidth > 0 && *sarHeight > 0) && (*sarWidth != 1 || *sarHeight != 1)) { ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d) " "SAR %d : %d", *width, *height, AVCProfileToString(profile), level / 10, level % 10, *sarWidth, *sarHeight); } else { // We treat *:0 and 0:* (unspecified) as 1:1. *sarWidth = 0; *sarHeight = 0; ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", *width, *height, AVCProfileToString(profile), level / 10, level % 10); } } return csd; }