• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 "extractor"
19 
20 #include <iostream>
21 
22 #include "Extractor.h"
23 
initExtractor(int32_t fd,size_t fileSize)24 int32_t Extractor::initExtractor(int32_t fd, size_t fileSize) {
25     mStats = new Stats();
26 
27     mFrameBuf = (uint8_t *)calloc(kMaxBufferSize, sizeof(uint8_t));
28     if (!mFrameBuf) return -1;
29 
30     int64_t sTime = mStats->getCurTime();
31 
32     mExtractor = AMediaExtractor_new();
33     if (!mExtractor) return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
34     media_status_t status = AMediaExtractor_setDataSourceFd(mExtractor, fd, 0, fileSize);
35     if (status != AMEDIA_OK) return status;
36 
37     int64_t eTime = mStats->getCurTime();
38     int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
39     mStats->setInitTime(timeTaken);
40 
41     return AMediaExtractor_getTrackCount(mExtractor);
42 }
43 
getCSDSample(AMediaCodecBufferInfo & frameInfo,int32_t csdIndex)44 void *Extractor::getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex) {
45     char csdName[kMaxCSDStrlen];
46     void *csdBuffer = nullptr;
47     frameInfo.presentationTimeUs = 0;
48     frameInfo.flags = AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
49     snprintf(csdName, sizeof(csdName), "csd-%d", csdIndex);
50 
51     size_t size;
52     bool csdFound = AMediaFormat_getBuffer(mFormat, csdName, &csdBuffer, &size);
53     if (!csdFound) return nullptr;
54     frameInfo.size = (int32_t)size;
55     mStats->addFrameSize(frameInfo.size);
56 
57     return csdBuffer;
58 }
59 
getFrameSample(AMediaCodecBufferInfo & frameInfo)60 int32_t Extractor::getFrameSample(AMediaCodecBufferInfo &frameInfo) {
61     int32_t size = AMediaExtractor_readSampleData(mExtractor, mFrameBuf, kMaxBufferSize);
62     if (size < 0) return -1;
63 
64     frameInfo.flags = AMediaExtractor_getSampleFlags(mExtractor);
65     frameInfo.size = size;
66     mStats->addFrameSize(frameInfo.size);
67     frameInfo.presentationTimeUs = AMediaExtractor_getSampleTime(mExtractor);
68     AMediaExtractor_advance(mExtractor);
69 
70     return 0;
71 }
72 
setupTrackFormat(int32_t trackId)73 int32_t Extractor::setupTrackFormat(int32_t trackId) {
74     AMediaExtractor_selectTrack(mExtractor, trackId);
75     mFormat = AMediaExtractor_getTrackFormat(mExtractor, trackId);
76     if (!mFormat) return AMEDIA_ERROR_INVALID_OBJECT;
77 
78     bool durationFound = AMediaFormat_getInt64(mFormat, AMEDIAFORMAT_KEY_DURATION, &mDurationUs);
79     if (!durationFound) return AMEDIA_ERROR_INVALID_OBJECT;
80 
81     return AMEDIA_OK;
82 }
83 
extract(int32_t trackId)84 int32_t Extractor::extract(int32_t trackId) {
85     int32_t status = setupTrackFormat(trackId);
86     if (status != AMEDIA_OK) return status;
87 
88     int32_t idx = 0;
89     AMediaCodecBufferInfo frameInfo;
90     while (1) {
91         memset(&frameInfo, 0, sizeof(AMediaCodecBufferInfo));
92         void *csdBuffer = getCSDSample(frameInfo, idx);
93         if (!csdBuffer || !frameInfo.size) break;
94         idx++;
95     }
96 
97     mStats->setStartTime();
98     while (1) {
99         int32_t status = getFrameSample(frameInfo);
100         if (status || !frameInfo.size) break;
101         mStats->addOutputTime();
102     }
103 
104     if (mFormat) {
105         AMediaFormat_delete(mFormat);
106         mFormat = nullptr;
107     }
108 
109     AMediaExtractor_unselectTrack(mExtractor, trackId);
110 
111     return AMEDIA_OK;
112 }
113 
dumpStatistics(string inputReference,string componentName,string statsFile)114 void Extractor::dumpStatistics(string inputReference, string componentName, string statsFile) {
115     string operation = "extract";
116     mStats->dumpStatistics(operation, inputReference, mDurationUs, componentName, "", statsFile);
117 }
118 
deInitExtractor()119 void Extractor::deInitExtractor() {
120     if (mFrameBuf) {
121         free(mFrameBuf);
122         mFrameBuf = nullptr;
123     }
124 
125     int64_t sTime = mStats->getCurTime();
126     if (mExtractor) {
127         // TODO: (b/140128505) Multiple calls result in DoS.
128         // Uncomment call to AMediaExtractor_delete() once this is resolved
129         // AMediaExtractor_delete(mExtractor);
130         mExtractor = nullptr;
131     }
132     int64_t eTime = mStats->getCurTime();
133     int64_t deInitTime = mStats->getTimeDiff(sTime, eTime);
134     mStats->setDeInitTime(deInitTime);
135 }
136