HEVC集成

https://zh.osdn.net/projects/android-x86/scm/git/frameworks-av/commits/9aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5e


frameworks-av: Commit

frameworks/av


Commit MetaInfo

修订版 9aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5e (tree)
时间 2016-01-22 05:47:05
作者 Wonsik Kim <wonsik@goog...>
Commiter Wonsik Kim

Log Message

stagefright: add HEVC support to MediaRecorder 

Bug: 22879917 
Change-Id: I6c97b051467de44c506a8ff021321e5953a63fc3 

更改概述

差异

--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
    @@ -95,6 +95,7 @@ enum video_encoder {
95 95 VIDEO_ENCODER_H264 = 2,
96 96 VIDEO_ENCODER_MPEG_4_SP = 3,
97 97 VIDEO_ENCODER_VP8 = 4,
  98 + VIDEO_ENCODER_HEVC = 5,
98 99  
99 100 VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
100 101 };
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
    @@ -37,7 +37,8 @@ MediaProfiles *MediaProfiles::sInstance = NULL;
37 37 const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
38 38 {"h263", VIDEO_ENCODER_H263},
39 39 {"h264", VIDEO_ENCODER_H264},
40   - {"m4v", VIDEO_ENCODER_MPEG_4_SP}
  40 + {"m4v", VIDEO_ENCODER_MPEG_4_SP},
  41 + {"hevc", VIDEO_ENCODER_HEVC}
41 42 };
42 43  
43 44 const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
    @@ -1226,6 +1226,7 @@ status_t StagefrightRecorder::checkVideoEncoderCapabilities() {
1226 1226 (mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 :
1227 1227 mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 :
1228 1228 mVideoEncoder == VIDEO_ENCODER_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 :
  1229 + mVideoEncoder == VIDEO_ENCODER_HEVC ? MEDIA_MIMETYPE_VIDEO_HEVC :
1229 1230 mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""),
1230 1231 false /* decoder */, true /* hwCodec */, &codecs);
1231 1232  
    @@ -1515,6 +1516,10 @@ status_t StagefrightRecorder::setupVideoEncoder(
1515 1516 format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
1516 1517 break;
1517 1518  
  1519 + case VIDEO_ENCODER_HEVC:
  1520 + format->setString("mime", MEDIA_MIMETYPE_VIDEO_HEVC);
  1521 + break;
  1522 +
1518 1523 default:
1519 1524 CHECK(!"Should not be here, unsupported video encoding.");
1520 1525 break;
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
    @@ -3530,8 +3530,8 @@ status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
3530 3530 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3531 3531 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3532 3532 }
3533   -
3534   - // TODO: Need OMX structure definition for setting iFrameInterval
  3533 + // TODO: finer control?
  3534 + hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3535 3535  
3536 3536 err = mOMX->setParameter(
3537 3537 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
    @@ -24,6 +24,7 @@ LOCAL_SRC_FILES:= \
24 24 FLACExtractor.cpp \
25 25 FrameRenderTracker.cpp \
26 26 HTTPBase.cpp \
  27 + HevcUtils.cpp \
27 28 JPEGSource.cpp \
28 29 MP3Extractor.cpp \
29 30 MPEG2TSWriter.cpp \
--- /dev/null
+++ b/media/libstagefright/HevcUtils.cpp
    @@ -0,0 +1,337 @@
  1 +/*
  2 + * Copyright (C) 2015 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 +//#define LOG_NDEBUG 0
  18 +#define LOG_TAG "HevcUtils"
  19 +
  20 +#include <cstring>
  21 +
  22 +#include "include/HevcUtils.h"
  23 +#include "include/avc_utils.h"
  24 +
  25 +#include <media/stagefright/foundation/ABitReader.h>
  26 +#include <media/stagefright/foundation/ABuffer.h>
  27 +#include <media/stagefright/foundation/ADebug.h>
  28 +#include <media/stagefright/foundation/AMessage.h>
  29 +#include <media/stagefright/MediaErrors.h>
  30 +#include <media/stagefright/Utils.h>
  31 +
  32 +namespace android {
  33 +
  34 +static const uint8_t kHevcNalUnitTypes[5] = {
  35 + kHevcNalUnitTypeVps,
  36 + kHevcNalUnitTypeSps,
  37 + kHevcNalUnitTypePps,
  38 + kHevcNalUnitTypePrefixSei,
  39 + kHevcNalUnitTypeSuffixSei,
  40 +};
  41 +
  42 +HevcParameterSets::HevcParameterSets() {
  43 +}
  44 +
  45 +status_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
  46 + uint8_t nalUnitType = (data[0] >> 1) & 0x3f;
  47 + status_t err = OK;
  48 + switch (nalUnitType) {
  49 + case 32: // VPS
  50 + err = parseVps(data + 2, size - 2);
  51 + break;
  52 + case 33: // SPS
  53 + err = parseSps(data + 2, size - 2);
  54 + break;
  55 + case 34: // PPS
  56 + err = parsePps(data + 2, size - 2);
  57 + break;
  58 + case 39: // Prefix SEI
  59 + case 40: // Suffix SEI
  60 + // Ignore
  61 + break;
  62 + default:
  63 + ALOGE("Unrecognized NAL unit type.");
  64 + return ERROR_MALFORMED;
  65 + }
  66 +
  67 + if (err != OK) {
  68 + return err;
  69 + }
  70 +
  71 + sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
  72 + buffer->setInt32Data(nalUnitType);
  73 + mNalUnits.push(buffer);
  74 + return OK;
  75 +}
  76 +
  77 +template <typename T>
  78 +static bool findParam(uint32_t key, T *param,
  79 + KeyedVector<uint32_t, uint64_t> &params) {
  80 + CHECK(param);
  81 + if (params.indexOfKey(key) < 0) {
  82 + return false;
  83 + }
  84 + *param = (T) params[key];
  85 + return true;
  86 +}
  87 +
  88 +bool HevcParameterSets::findParam8(uint32_t key, uint8_t *param) {
  89 + return findParam(key, param, mParams);
  90 +}
  91 +
  92 +bool HevcParameterSets::findParam16(uint32_t key, uint16_t *param) {
  93 + return findParam(key, param, mParams);
  94 +}
  95 +
  96 +bool HevcParameterSets::findParam32(uint32_t key, uint32_t *param) {
  97 + return findParam(key, param, mParams);
  98 +}
  99 +
  100 +bool HevcParameterSets::findParam64(uint32_t key, uint64_t *param) {
  101 + return findParam(key, param, mParams);
  102 +}
  103 +
  104 +size_t HevcParameterSets::getNumNalUnitsOfType(uint8_t type) {
  105 + size_t num = 0;
  106 + for (size_t i = 0; i < mNalUnits.size(); ++i) {
  107 + if (getType(i) == type) {
  108 + ++num;
  109 + }
  110 + }
  111 + return num;
  112 +}
  113 +
  114 +uint8_t HevcParameterSets::getType(size_t index) {
  115 + CHECK_LT(index, mNalUnits.size());
  116 + return mNalUnits[index]->int32Data();
  117 +}
  118 +
  119 +size_t HevcParameterSets::getSize(size_t index) {
  120 + CHECK_LT(index, mNalUnits.size());
  121 + return mNalUnits[index]->size();
  122 +}
  123 +
  124 +bool HevcParameterSets::write(size_t index, uint8_t* dest, size_t size) {
  125 + CHECK_LT(index, mNalUnits.size());
  126 + const sp<ABuffer>& nalUnit = mNalUnits[index];
  127 + if (size < nalUnit->size()) {
  128 + ALOGE("dest buffer size too small: %zu vs. %zu to be written",
  129 + size, nalUnit->size());
  130 + return false;
  131 + }
  132 + memcpy(dest, nalUnit->data(), nalUnit->size());
  133 + return true;
  134 +}
  135 +
  136 +status_t HevcParameterSets::parseVps(const uint8_t* data, size_t size) {
  137 + // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.1 for reference
  138 + NALBitReader reader(data, size);
  139 + // Skip vps_video_parameter_set_id
  140 + reader.skipBits(4);
  141 + // Skip vps_base_layer_internal_flag
  142 + reader.skipBits(1);
  143 + // Skip vps_base_layer_available_flag
  144 + reader.skipBits(1);
  145 + // Skip vps_max_layers_minus_1
  146 + reader.skipBits(6);
  147 + // Skip vps_temporal_id_nesting_flags
  148 + reader.skipBits(1);
  149 + // Skip reserved
  150 + reader.skipBits(16);
  151 +
  152 + mParams.add(kGeneralProfileSpace, reader.getBits(2));
  153 + mParams.add(kGeneralTierFlag, reader.getBits(1));
  154 + mParams.add(kGeneralProfileIdc, reader.getBits(5));
  155 + mParams.add(kGeneralProfileCompatibilityFlags, reader.getBits(32));
  156 + mParams.add(
  157 + kGeneralConstraintIndicatorFlags,
  158 + ((uint64_t)reader.getBits(16) << 32) | reader.getBits(32));
  159 + mParams.add(kGeneralLevelIdc, reader.getBits(8));
  160 + // 96 bits total for general profile.
  161 +
  162 + return OK;
  163 +}
  164 +
  165 +status_t HevcParameterSets::parseSps(const uint8_t* data, size_t size) {
  166 + // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.2 for reference
  167 + NALBitReader reader(data, size);
  168 + // Skip sps_video_parameter_set_id
  169 + reader.skipBits(4);
  170 + uint8_t maxSubLayersMinus1 = reader.getBits(3);
  171 + // Skip sps_temporal_id_nesting_flag;
  172 + reader.skipBits(1);
  173 + // Skip general profile
  174 + reader.skipBits(96);
  175 + if (maxSubLayersMinus1 > 0) {
  176 + bool subLayerProfilePresentFlag[8];
  177 + bool subLayerLevelPresentFlag[8];
  178 + for (int i = 0; i < maxSubLayersMinus1; ++i) {
  179 + subLayerProfilePresentFlag[i] = reader.getBits(1);
  180 + subLayerLevelPresentFlag[i] = reader.getBits(1);
  181 + }
  182 + // Skip reserved
  183 + reader.skipBits(2 * (8 - maxSubLayersMinus1));
  184 + for (int i = 0; i < maxSubLayersMinus1; ++i) {
  185 + if (subLayerProfilePresentFlag[i]) {
  186 + // Skip profile
  187 + reader.skipBits(88);
  188 + }
  189 + if (subLayerLevelPresentFlag[i]) {
  190 + // Skip sub_layer_level_idc[i]
  191 + reader.skipBits(8);
  192 + }
  193 + }
  194 + }
  195 + // Skip sps_seq_parameter_set_id
  196 + parseUE(&reader);
  197 + uint8_t chromaFormatIdc = parseUE(&reader);
  198 + mParams.add(kChromaFormatIdc, chromaFormatIdc);
  199 + if (chromaFormatIdc == 3) {
  200 + // Skip separate_colour_plane_flag
  201 + reader.skipBits(1);
  202 + }
  203 + // Skip pic_width_in_luma_samples
  204 + parseUE(&reader);
  205 + // Skip pic_height_in_luma_samples
  206 + parseUE(&reader);
  207 + if (reader.getBits(1) /* i.e. conformance_window_flag */) {
  208 + // Skip conf_win_left_offset
  209 + parseUE(&reader);
  210 + // Skip conf_win_right_offset
  211 + parseUE(&reader);
  212 + // Skip conf_win_top_offset
  213 + parseUE(&reader);
  214 + // Skip conf_win_bottom_offset
  215 + parseUE(&reader);
  216 + }
  217 + mParams.add(kBitDepthLumaMinus8, parseUE(&reader));
  218 + mParams.add(kBitDepthChromaMinus8, parseUE(&reader));
  219 +
  220 + return OK;
  221 +}
  222 +
  223 +status_t HevcParameterSets::parsePps(
  224 + const uint8_t* data __unused, size_t size __unused) {
  225 + return OK;
  226 +}
  227 +
  228 +status_t HevcParameterSets::makeHvcc(uint8_t *hvcc, size_t *hvccSize,
  229 + size_t nalSizeLength) {
  230 + if (hvcc == NULL || hvccSize == NULL
  231 + || (nalSizeLength != 4 && nalSizeLength != 2)) {
  232 + return BAD_VALUE;
  233 + }
  234 + // ISO 14496-15: HEVC file format
  235 + size_t size = 23; // 23 bytes in the header
  236 + size_t numOfArrays = 0;
  237 + const size_t numNalUnits = getNumNalUnits();
  238 + for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
  239 + uint8_t type = kHevcNalUnitTypes[i];
  240 + size_t numNalus = getNumNalUnitsOfType(type);
  241 + if (numNalus == 0) {
  242 + continue;
  243 + }
  244 + ++numOfArrays;
  245 + size += 3;
  246 + for (size_t j = 0; j < numNalUnits; ++j) {
  247 + if (getType(j) != type) {
  248 + continue;
  249 + }
  250 + size += 2 + getSize(j);
  251 + }
  252 + }
  253 + uint8_t generalProfileSpace, generalTierFlag, generalProfileIdc;
  254 + if (!findParam8(kGeneralProfileSpace, &generalProfileSpace)
  255 + || !findParam8(kGeneralTierFlag, &generalTierFlag)
  256 + || !findParam8(kGeneralProfileIdc, &generalProfileIdc)) {
  257 + return ERROR_MALFORMED;
  258 + }
  259 + uint32_t compatibilityFlags;
  260 + uint64_t constraintIdcFlags;
  261 + if (!findParam32(kGeneralProfileCompatibilityFlags, &compatibilityFlags)
  262 + || !findParam64(kGeneralConstraintIndicatorFlags, &constraintIdcFlags)) {
  263 + return ERROR_MALFORMED;
  264 + }
  265 + uint8_t generalLevelIdc;
  266 + if (!findParam8(kGeneralLevelIdc, &generalLevelIdc)) {
  267 + return ERROR_MALFORMED;
  268 + }
  269 + uint8_t chromaFormatIdc, bitDepthLumaMinus8, bitDepthChromaMinus8;
  270 + if (!findParam8(kChromaFormatIdc, &chromaFormatIdc)
  271 + || !findParam8(kBitDepthLumaMinus8, &bitDepthLumaMinus8)
  272 + || !findParam8(kBitDepthChromaMinus8, &bitDepthChromaMinus8)) {
  273 + return ERROR_MALFORMED;
  274 + }
  275 + if (size > *hvccSize) {
  276 + return NO_MEMORY;
  277 + }
  278 + *hvccSize = size;
  279 +
  280 + uint8_t *header = hvcc;
  281 + header[0] = 1;
  282 + header[1] = (kGeneralProfileSpace << 6) | (kGeneralTierFlag << 5) | kGeneralProfileIdc;
  283 + header[2] = (compatibilityFlags >> 24) & 0xff;
  284 + header[3] = (compatibilityFlags >> 16) & 0xff;
  285 + header[4] = (compatibilityFlags >> 8) & 0xff;
  286 + header[5] = compatibilityFlags & 0xff;
  287 + header[6] = (constraintIdcFlags >> 40) & 0xff;
  288 + header[7] = (constraintIdcFlags >> 32) & 0xff;
  289 + header[8] = (constraintIdcFlags >> 24) & 0xff;
  290 + header[9] = (constraintIdcFlags >> 16) & 0xff;
  291 + header[10] = (constraintIdcFlags >> 8) & 0xff;
  292 + header[11] = constraintIdcFlags & 0xff;
  293 + header[12] = generalLevelIdc;
  294 + // FIXME: parse min_spatial_segmentation_idc.
  295 + header[13] = 0xf0;
  296 + header[14] = 0;
  297 + // FIXME: derive parallelismType properly.
  298 + header[15] = 0xfc;
  299 + header[16] = 0xfc | chromaFormatIdc;
  300 + header[17] = 0xf8 | bitDepthLumaMinus8;
  301 + header[18] = 0xf8 | bitDepthChromaMinus8;
  302 + // FIXME: derive avgFrameRate
  303 + header[19] = 0;
  304 + header[20] = 0;
  305 + // constantFrameRate, numTemporalLayers, temporalIdNested all set to 0.
  306 + header[21] = nalSizeLength - 1;
  307 + header[22] = numOfArrays;
  308 + header += 23;
  309 + for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
  310 + uint8_t type = kHevcNalUnitTypes[i];
  311 + size_t numNalus = getNumNalUnitsOfType(type);
  312 + if (numNalus == 0) {
  313 + continue;
  314 + }
  315 + // array_completeness set to 0.
  316 + header[0] = type;
  317 + header[1] = (numNalus >> 8) & 0xff;
  318 + header[2] = numNalus & 0xff;
  319 + header += 3;
  320 + for (size_t j = 0; j < numNalUnits; ++j) {
  321 + if (getType(j) != type) {
  322 + continue;
  323 + }
  324 + header[0] = (getSize(j) >> 8) & 0xff;
  325 + header[1] = getSize(j) & 0xff;
  326 + if (!write(j, header + 2, size - (header - (uint8_t *)hvcc))) {
  327 + return NO_MEMORY;
  328 + }
  329 + header += (2 + getSize(j));
  330 + }
  331 + }
  332 + CHECK_EQ(header - size, hvcc);
  333 +
  334 + return OK;
  335 +}
  336 +
  337 +} // namespace android
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
    @@ -41,7 +41,7 @@
41 41 #include <cutils/properties.h>
42 42  
43 43 #include "include/ESDS.h"
44   -
  44 +#include "include/HevcUtils.h"
45 45  
46 46 #ifndef __predict_false
47 47 #define __predict_false(exp) __builtin_expect((exp) != 0, 0)
    @@ -70,6 +70,18 @@ static const char kMetaKey_Build[] = "com.android.build";
70 70 #endif
71 71 static const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
72 72  
  73 +static const uint8_t kMandatoryHevcNalUnitTypes[3] = {
  74 + kHevcNalUnitTypeVps,
  75 + kHevcNalUnitTypeSps,
  76 + kHevcNalUnitTypePps,
  77 +};
  78 +static const uint8_t kHevcNalUnitTypes[5] = {
  79 + kHevcNalUnitTypeVps,
  80 + kHevcNalUnitTypeSps,
  81 + kHevcNalUnitTypePps,
  82 + kHevcNalUnitTypePrefixSei,
  83 + kHevcNalUnitTypeSuffixSei,
  84 +};
73 85 /* uncomment to include model and build in meta */
74 86 //#define SHOW_MODEL_BUILD 1
75 87  
    @@ -89,6 +101,7 @@ public:
89 101 void writeTrackHeader(bool use32BitOffset = true);
90 102 void bufferChunk(int64_t timestampUs);
91 103 bool isAvc() const { return mIsAvc; }
  104 + bool isHevc() const { return mIsHevc; }
92 105 bool isAudio() const { return mIsAudio; }
93 106 bool isMPEG4() const { return mIsMPEG4; }
94 107 void addChunkOffset(off64_t offset);
    @@ -234,6 +247,7 @@ private:
234 247 volatile bool mResumed;
235 248 volatile bool mStarted;
236 249 bool mIsAvc;
  250 + bool mIsHevc;
237 251 bool mIsAudio;
238 252 bool mIsMPEG4;
239 253 int32_t mTrackId;
    @@ -299,10 +313,17 @@ private:
299 313 const uint8_t *parseParamSet(
300 314 const uint8_t *data, size_t length, int type, size_t *paramSetLen);
301 315  
  316 + status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
  317 +
302 318 status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
303 319 status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
304 320 status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
305 321  
  322 + status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
  323 + status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
  324 + status_t parseHEVCCodecSpecificData(
  325 + const uint8_t *data, size_t size, HevcParameterSets &paramSets);
  326 +
306 327 // Track authoring progress status
307 328 void trackProgressStatus(int64_t timeUs, status_t err = OK);
308 329 void initTrackingProgressStatus(MetaData *params);
    @@ -340,6 +361,7 @@ private:
340 361 void writeD263Box();
341 362 void writePaspBox();
342 363 void writeAvccBox();
  364 + void writeHvccBox();
343 365 void writeUrlBox();
344 366 void writeDrefBox();
345 367 void writeDinfBox();
    @@ -463,6 +485,8 @@ const char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
463 485 return "s263";
464 486 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
465 487 return "avc1";
  488 + } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
  489 + return "hvc1";
466 490 }
467 491 } else {
468 492 ALOGE("Track (%s) other than video or audio is not supported", mime);
    @@ -1465,6 +1489,7 @@ MPEG4Writer::Track::Track(
1465 1489 const char *mime;
1466 1490 mMeta->findCString(kKeyMIMEType, &mime);
1467 1491 mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
  1492 + mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
1468 1493 mIsAudio = !strncasecmp(mime, "audio/", 6);
1469 1494 mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
1470 1495 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
    @@ -1560,31 +1585,26 @@ void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
1560 1585 const char *mime;
1561 1586 CHECK(mMeta->findCString(kKeyMIMEType, &mime));
1562 1587  
  1588 + uint32_t type;
  1589 + const void *data = NULL;
  1590 + size_t size = 0;
1563 1591 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1564   - uint32_t type;
1565   - const void *data;
1566   - size_t size;
1567   - if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
1568   - mCodecSpecificData = malloc(size);
1569   - mCodecSpecificDataSize = size;
1570   - memcpy(mCodecSpecificData, data, size);
1571   - mGotAllCodecSpecificData = true;
1572   - }
  1592 + mMeta->findData(kKeyAVCC, &type, &data, &size);
  1593 + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
  1594 + mMeta->findData(kKeyHVCC, &type, &data, &size);
1573 1595 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1574 1596 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1575   - uint32_t type;
1576   - const void *data;
1577   - size_t size;
1578 1597 if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
1579 1598 ESDS esds(data, size);
1580   - if (esds.getCodecSpecificInfo(&data, &size) == OK) {
1581   - mCodecSpecificData = malloc(size);
1582   - mCodecSpecificDataSize = size;
1583   - memcpy(mCodecSpecificData, data, size);
1584   - mGotAllCodecSpecificData = true;
  1599 + if (esds.getCodecSpecificInfo(&data, &size) != OK) {
  1600 + data = NULL;
  1601 + size = 0;
1585 1602 }
1586 1603 }
1587 1604 }
  1605 + if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
  1606 + mGotAllCodecSpecificData = true;
  1607 + }
1588 1608 }
1589 1609  
1590 1610 MPEG4Writer::Track::~Track() {
    @@ -1661,7 +1681,7 @@ void MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1661 1681 while (!chunk->mSamples.empty()) {
1662 1682 List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1663 1683  
1664   - off64_t offset = chunk->mTrack->isAvc()
  1684 + off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
1665 1685 ? addLengthPrefixedSample_l(*it)
1666 1686 : addSample_l(*it);
1667 1687  
    @@ -1968,13 +1988,30 @@ status_t MPEG4Writer::Track::copyAVCCodecSpecificData(
1968 1988  
1969 1989 // 2 bytes for each of the parameter set length field
1970 1990 // plus the 7 bytes for the header
1971   - if (size < 4 + 7) {
  1991 + return copyCodecSpecificData(data, size, 4 + 7);
  1992 +}
  1993 +
  1994 +status_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
  1995 + const uint8_t *data, size_t size) {
  1996 + ALOGV("copyHEVCCodecSpecificData");
  1997 +
  1998 + // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
  1999 + return copyCodecSpecificData(data, size, 23);
  2000 +}
  2001 +
  2002 +status_t MPEG4Writer::Track::copyCodecSpecificData(
  2003 + const uint8_t *data, size_t size, size_t minLength) {
  2004 + if (size < minLength) {
1972 2005 ALOGE("Codec specific data length too short: %zu", size);
1973 2006 return ERROR_MALFORMED;
1974 2007 }
1975 2008  
1976   - mCodecSpecificDataSize = size;
1977 2009 mCodecSpecificData = malloc(size);
  2010 + if (mCodecSpecificData == NULL) {
  2011 + ALOGE("Failed allocating codec specific data");
  2012 + return NO_MEMORY;
  2013 + }
  2014 + mCodecSpecificDataSize = size;
1978 2015 memcpy(mCodecSpecificData, data, size);
1979 2016 return OK;
1980 2017 }
    @@ -2097,6 +2134,11 @@ status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
2097 2134 // ISO 14496-15: AVC file format
2098 2135 mCodecSpecificDataSize += 7; // 7 more bytes in the header
2099 2136 mCodecSpecificData = malloc(mCodecSpecificDataSize);
  2137 + if (mCodecSpecificData == NULL) {
  2138 + mCodecSpecificDataSize = 0;
  2139 + ALOGE("Failed allocating codec specific data");
  2140 + return NO_MEMORY;
  2141 + }
2100 2142 uint8_t *header = (uint8_t *)mCodecSpecificData;
2101 2143 header[0] = 1; // version
2102 2144 header[1] = mProfileIdc; // profile indication
    @@ -2145,6 +2187,96 @@ status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
2145 2187 return OK;
2146 2188 }
2147 2189  
  2190 +
  2191 +status_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
  2192 + const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
  2193 +
  2194 + ALOGV("parseHEVCCodecSpecificData");
  2195 + const uint8_t *tmp = data;
  2196 + const uint8_t *nextStartCode = data;
  2197 + size_t bytesLeft = size;
  2198 + while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
  2199 + nextStartCode = findNextStartCode(tmp + 4, bytesLeft - 4);
  2200 + if (nextStartCode == NULL) {
  2201 + return ERROR_MALFORMED;
  2202 + }
  2203 + status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
  2204 + if (err != OK) {
  2205 + return ERROR_MALFORMED;
  2206 + }
  2207 +
  2208 + // Move on to find the next parameter set
  2209 + bytesLeft -= nextStartCode - tmp;
  2210 + tmp = nextStartCode;
  2211 + }
  2212 +
  2213 + size_t csdSize = 23;
  2214 + const size_t numNalUnits = paramSets.getNumNalUnits();
  2215 + for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
  2216 + int type = kMandatoryHevcNalUnitTypes[i];
  2217 + size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
  2218 + if (numParamSets == 0) {
  2219 + ALOGE("Cound not find NAL unit of type %d", type);
  2220 + return ERROR_MALFORMED;
  2221 + }
  2222 + }
  2223 + for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
  2224 + int type = kHevcNalUnitTypes[i];
  2225 + size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
  2226 + if (numParamSets > 0xffff) {
  2227 + ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
  2228 + return ERROR_MALFORMED;
  2229 + }
  2230 + csdSize += 3;
  2231 + for (size_t j = 0; j < numNalUnits; ++j) {
  2232 + if (paramSets.getType(j) != type) {
  2233 + continue;
  2234 + }
  2235 + csdSize += 2 + paramSets.getSize(j);
  2236 + }
  2237 + }
  2238 + mCodecSpecificDataSize = csdSize;
  2239 + return OK;
  2240 +}
  2241 +
  2242 +status_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
  2243 + const uint8_t *data, size_t size) {
  2244 +
  2245 + if (mCodecSpecificData != NULL) {
  2246 + ALOGE("Already have codec specific data");
  2247 + return ERROR_MALFORMED;
  2248 + }
  2249 +
  2250 + if (size < 4) {
  2251 + ALOGE("Codec specific data length too short: %zu", size);
  2252 + return ERROR_MALFORMED;
  2253 + }
  2254 +
  2255 + // Data is in the form of HEVCCodecSpecificData
  2256 + if (memcmp("\x00\x00\x00\x01", data, 4)) {
  2257 + return copyHEVCCodecSpecificData(data, size);
  2258 + }
  2259 +
  2260 + HevcParameterSets paramSets;
  2261 + if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
  2262 + return ERROR_MALFORMED;
  2263 + }
  2264 +
  2265 + mCodecSpecificData = malloc(mCodecSpecificDataSize);
  2266 + if (mCodecSpecificData == NULL) {
  2267 + mCodecSpecificDataSize = 0;
  2268 + ALOGE("Failed allocating codec specific data");
  2269 + return NO_MEMORY;
  2270 + }
  2271 + status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
  2272 + &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 5 : 2);
  2273 + if (err != OK) {
  2274 + return err;
  2275 + }
  2276 +
  2277 + return OK;
  2278 +}
  2279 +
2148 2280 /*
2149 2281 * Updates the drift time from the audio track so that
2150 2282 * the video track can get the updated drift time information
    @@ -2228,13 +2360,15 @@ status_t MPEG4Writer::Track::threadEntry() {
2228 2360 + buffer->range_offset(),
2229 2361 buffer->range_length());
2230 2362 CHECK_EQ((status_t)OK, err);
2231   - } else if (mIsMPEG4) {
2232   - mCodecSpecificDataSize = buffer->range_length();
2233   - mCodecSpecificData = malloc(mCodecSpecificDataSize);
2234   - memcpy(mCodecSpecificData,
  2363 + } else if (mIsHevc) {
  2364 + status_t err = makeHEVCCodecSpecificData(
2235 2365 (const uint8_t *)buffer->data()
2236 2366 + buffer->range_offset(),
2237   - buffer->range_length());
  2367 + buffer->range_length());
  2368 + CHECK_EQ((status_t)OK, err);
  2369 + } else if (mIsMPEG4) {
  2370 + copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
  2371 + buffer->range_length());
2238 2372 }
2239 2373  
2240 2374 buffer->release();
    @@ -2254,10 +2388,10 @@ status_t MPEG4Writer::Track::threadEntry() {
2254 2388 buffer->release();
2255 2389 buffer = NULL;
2256 2390  
2257   - if (mIsAvc) StripStartcode(copy);
  2391 + if (mIsAvc || mIsHevc) StripStartcode(copy);
2258 2392  
2259 2393 size_t sampleSize = copy->range_length();
2260   - if (mIsAvc) {
  2394 + if (mIsAvc || mIsHevc) {
2261 2395 if (mOwner->useNalLengthFour()) {
2262 2396 sampleSize += 4;
2263 2397 } else {
    @@ -2457,7 +2591,7 @@ status_t MPEG4Writer::Track::threadEntry() {
2457 2591 trackProgressStatus(timestampUs);
2458 2592 }
2459 2593 if (!hasMultipleTracks) {
2460   - off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
  2594 + off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
2461 2595 : mOwner->addSample_l(copy);
2462 2596  
2463 2597 uint32_t count = (mOwner->use32BitFileOffset()
    @@ -2709,7 +2843,8 @@ status_t MPEG4Writer::Track::checkCodecSpecificData() const {
2709 2843 CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2710 2844 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2711 2845 !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2712   - !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
  2846 + !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
  2847 + !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2713 2848 if (!mCodecSpecificData ||
2714 2849 mCodecSpecificDataSize <= 0) {
2715 2850 ALOGE("Missing codec specific data");
    @@ -2815,6 +2950,8 @@ void MPEG4Writer::Track::writeVideoFourCCBox() {
2815 2950 writeD263Box();
2816 2951 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2817 2952 writeAvccBox();
  2953 + } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
  2954 + writeHvccBox();
2818 2955 }
2819 2956  
2820 2957 writePaspBox();
    @@ -3070,6 +3207,20 @@ void MPEG4Writer::Track::writeAvccBox() {
3070 3207 mOwner->endBox(); // avcC
3071 3208 }
3072 3209  
  3210 +
  3211 +void MPEG4Writer::Track::writeHvccBox() {
  3212 + CHECK(mCodecSpecificData);
  3213 + CHECK_GE(mCodecSpecificDataSize, 5);
  3214 +
  3215 + // Patch avcc's lengthSize field to match the number
  3216 + // of bytes we use to indicate the size of a nal unit.
  3217 + uint8_t *ptr = (uint8_t *)mCodecSpecificData;
  3218 + ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
  3219 + mOwner->beginBox("hvcC");
  3220 + mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
  3221 + mOwner->endBox(); // hvcC
  3222 +}
  3223 +
3073 3224 void MPEG4Writer::Track::writeD263Box() {
3074 3225 mOwner->beginBox("d263");
3075 3226 mOwner->writeInt32(0); // vendor
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
    @@ -22,6 +22,7 @@
22 22 #include <sys/stat.h>
23 23  
24 24 #include "include/ESDS.h"
  25 +#include "include/HevcUtils.h"
25 26  
26 27 #include <arpa/inet.h>
27 28 #include <cutils/properties.h>
    @@ -575,6 +576,41 @@ static void reassembleESDS(const sp<ABuffer> &csd0, char *esds) {
575 576  
576 577 }
577 578  
  579 +static size_t reassembleHVCC(const sp<ABuffer> &csd0, uint8_t *hvcc, size_t hvccSize, size_t nalSizeLength) {
  580 + HevcParameterSets paramSets;
  581 + uint8_t* data = csd0->data();
  582 + if (csd0->size() < 4) {
  583 + ALOGE("csd0 too small");
  584 + return 0;
  585 + }
  586 + if (memcmp(data, "\x00\x00\x00\x01", 4) != 0) {
  587 + ALOGE("csd0 doesn't start with a start code");
  588 + return 0;
  589 + }
  590 + size_t prevNalOffset = 4;
  591 + status_t err = OK;
  592 + for (size_t i = 1; i < csd0->size() - 4; ++i) {
  593 + if (memcmp(&data[i], "\x00\x00\x00\x01", 4) != 0) {
  594 + continue;
  595 + }
  596 + err = paramSets.addNalUnit(&data[prevNalOffset], i - prevNalOffset);
  597 + if (err != OK) {
  598 + return 0;
  599 + }
  600 + prevNalOffset = i + 4;
  601 + }
  602 + err = paramSets.addNalUnit(&data[prevNalOffset], csd0->size() - prevNalOffset);
  603 + if (err != OK) {
  604 + return 0;
  605 + }
  606 + size_t size = hvccSize;
  607 + err = paramSets.makeHvcc(hvcc, &size, nalSizeLength);
  608 + if (err != OK) {
  609 + return 0;
  610 + }
  611 + return size;
  612 +}
  613 +
578 614 void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
579 615 AString mime;
580 616 if (msg->findString("mime", &mime)) {
    @@ -693,6 +729,10 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
693 729 // for transporting the CSD to muxers.
694 730 reassembleESDS(csd0, esds);
695 731 meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds));
  732 + } else if (mime == MEDIA_MIMETYPE_VIDEO_HEVC) {
  733 + uint8_t hvcc[1024]; // that oughta be enough, right?
  734 + size_t outsize = reassembleHVCC(csd0, hvcc, 1024, 4);
  735 + meta->setData(kKeyHVCC, kKeyHVCC, hvcc, outsize);
696 736 }
697 737 }
698 738  
--- /dev/null
+++ b/media/libstagefright/include/HevcUtils.h
    @@ -0,0 +1,93 @@
  1 +/*
  2 + * Copyright (C) 2015 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 +#ifndef HEVC_UTILS_H_
  18 +
  19 +#define HEVC_UTILS_H_
  20 +
  21 +#include <stdint.h>
  22 +
  23 +#include <media/stagefright/foundation/ABase.h>
  24 +#include <media/stagefright/foundation/ABuffer.h>
  25 +#include <utils/Errors.h>
  26 +#include <utils/KeyedVector.h>
  27 +#include <utils/StrongPointer.h>
  28 +#include <utils/Vector.h>
  29 +
  30 +namespace android {
  31 +
  32 +enum {
  33 + kHevcNalUnitTypeVps = 32,
  34 + kHevcNalUnitTypeSps = 33,
  35 + kHevcNalUnitTypePps = 34,
  36 + kHevcNalUnitTypePrefixSei = 39,
  37 + kHevcNalUnitTypeSuffixSei = 40,
  38 +};
  39 +
  40 +enum {
  41 + // uint8_t
  42 + kGeneralProfileSpace,
  43 + // uint8_t
  44 + kGeneralTierFlag,
  45 + // uint8_t
  46 + kGeneralProfileIdc,
  47 + // uint32_t
  48 + kGeneralProfileCompatibilityFlags,
  49 + // uint64_t
  50 + kGeneralConstraintIndicatorFlags,
  51 + // uint8_t
  52 + kGeneralLevelIdc,
  53 + // uint8_t
  54 + kChromaFormatIdc,
  55 + // uint8_t
  56 + kBitDepthLumaMinus8,
  57 + // uint8_t
  58 + kBitDepthChromaMinus8,
  59 +};
  60 +
  61 +class HevcParameterSets {
  62 +public:
  63 + HevcParameterSets();
  64 +
  65 + status_t addNalUnit(const uint8_t* data, size_t size);
  66 +
  67 + bool findParam8(uint32_t key, uint8_t *param);
  68 + bool findParam16(uint32_t key, uint16_t *param);
  69 + bool findParam32(uint32_t key, uint32_t *param);
  70 + bool findParam64(uint32_t key, uint64_t *param);
  71 +
  72 + inline size_t getNumNalUnits() { return mNalUnits.size(); }
  73 + size_t getNumNalUnitsOfType(uint8_t type);
  74 + uint8_t getType(size_t index);
  75 + size_t getSize(size_t index);
  76 + // Note that this method does not write the start code.
  77 + bool write(size_t index, uint8_t* dest, size_t size);
  78 + status_t makeHvcc(uint8_t *hvcc, size_t *hvccSize, size_t nalSizeLength);
  79 +
  80 +private:
  81 + status_t parseVps(const uint8_t* data, size_t size);
  82 + status_t parseSps(const uint8_t* data, size_t size);
  83 + status_t parsePps(const uint8_t* data, size_t size);
  84 +
  85 + KeyedVector<uint32_t, uint64_t> mParams;
  86 + Vector<sp<ABuffer>> mNalUnits;
  87 +
  88 + DISALLOW_EVIL_CONSTRUCTORS(HevcParameterSets);
  89 +};
  90 +
  91 +} // namespace android
  92 +
  93 +#endif // HEVC_UTILS_H_



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值