LCOV - code coverage report
Current view: top level - media/libstagefright/frameworks/av/media/libstagefright - SampleIterator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 154 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #undef LOG_TAG
      18             : #define LOG_TAG "SampleIterator"
      19             : //#define LOG_NDEBUG 0
      20             : #include <utils/Log.h>
      21             : 
      22             : #include "include/SampleIterator.h"
      23             : 
      24             : #include <arpa/inet.h>
      25             : 
      26             : #include <media/stagefright/foundation/ADebug.h>
      27             : #include <media/stagefright/DataSource.h>
      28             : #include <media/stagefright/Utils.h>
      29             : 
      30             : #include "include/SampleTable.h"
      31             : 
      32             : namespace stagefright {
      33             : 
      34           0 : SampleIterator::SampleIterator(SampleTable *table)
      35             :     : mTable(table),
      36             :       mInitialized(false),
      37             :       mTimeToSampleIndex(0),
      38             :       mTTSSampleIndex(0),
      39             :       mTTSSampleTime(0),
      40             :       mTTSCount(0),
      41           0 :       mTTSDuration(0) {
      42           0 :     reset();
      43           0 : }
      44             : 
      45           0 : void SampleIterator::reset() {
      46           0 :     mSampleToChunkIndex = 0;
      47           0 :     mFirstChunk = 0;
      48           0 :     mFirstChunkSampleIndex = 0;
      49           0 :     mStopChunk = 0;
      50           0 :     mStopChunkSampleIndex = 0;
      51           0 :     mSamplesPerChunk = 0;
      52           0 :     mChunkDesc = 0;
      53           0 : }
      54             : 
      55           0 : status_t SampleIterator::seekTo(uint32_t sampleIndex) {
      56             :     ALOGV("seekTo(%d)", sampleIndex);
      57             : 
      58           0 :     if (sampleIndex >= mTable->mNumSampleSizes) {
      59           0 :         return ERROR_END_OF_STREAM;
      60             :     }
      61             : 
      62           0 :     if (mTable->mSampleToChunkOffset < 0
      63           0 :             || mTable->mChunkOffsetOffset < 0
      64           0 :             || mTable->mSampleSizeOffset < 0
      65           0 :             || mTable->mTimeToSampleCount == 0) {
      66             : 
      67           0 :         return ERROR_MALFORMED;
      68             :     }
      69             : 
      70           0 :     if (mInitialized && mCurrentSampleIndex == sampleIndex) {
      71           0 :         return OK;
      72             :     }
      73             : 
      74           0 :     if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) {
      75           0 :         reset();
      76             :     }
      77             : 
      78           0 :     if (sampleIndex >= mStopChunkSampleIndex) {
      79             :         status_t err;
      80           0 :         if ((err = findChunkRange(sampleIndex)) != OK) {
      81           0 :             ALOGE("findChunkRange failed");
      82           0 :             return err;
      83             :         }
      84             :     }
      85             : 
      86           0 :     if (sampleIndex >= mStopChunkSampleIndex) {
      87           0 :         return ERROR_MALFORMED;
      88             :     }
      89             : 
      90             :     uint32_t chunk =
      91           0 :         (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk
      92           0 :         + mFirstChunk;
      93             : 
      94           0 :     if (!mInitialized || chunk != mCurrentChunkIndex) {
      95           0 :         mCurrentChunkIndex = chunk;
      96             : 
      97             :         status_t err;
      98           0 :         if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
      99           0 :             ALOGE("getChunkOffset return error");
     100           0 :             return err;
     101             :         }
     102             : 
     103           0 :         mCurrentChunkSampleSizes.clear();
     104             : 
     105             :         uint32_t firstChunkSampleIndex =
     106           0 :             mFirstChunkSampleIndex
     107           0 :                 + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk);
     108             : 
     109           0 :         for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
     110             :             size_t sampleSize;
     111           0 :             if ((err = getSampleSizeDirect(
     112             :                             firstChunkSampleIndex + i, &sampleSize)) != OK) {
     113           0 :                 ALOGE("getSampleSizeDirect return error");
     114           0 :                 return err;
     115             :             }
     116             : 
     117           0 :             mCurrentChunkSampleSizes.push(sampleSize);
     118             :         }
     119             :     }
     120             : 
     121           0 :     if (mCurrentChunkSampleSizes.size() != mSamplesPerChunk) {
     122           0 :         return ERROR_MALFORMED;
     123             :     }
     124             : 
     125             :     uint32_t chunkRelativeSampleIndex =
     126           0 :         (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk;
     127             : 
     128             :     // This can never happen unless % operator is buggy.
     129           0 :     CHECK(chunkRelativeSampleIndex < mSamplesPerChunk);
     130             : 
     131           0 :     mCurrentSampleOffset = mCurrentChunkOffset;
     132           0 :     for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) {
     133           0 :         mCurrentSampleOffset += mCurrentChunkSampleSizes[i];
     134             :     }
     135             : 
     136           0 :     mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex];
     137           0 :     if (sampleIndex < mTTSSampleIndex) {
     138           0 :         mTimeToSampleIndex = 0;
     139           0 :         mTTSSampleIndex = 0;
     140           0 :         mTTSSampleTime = 0;
     141           0 :         mTTSCount = 0;
     142           0 :         mTTSDuration = 0;
     143             :     }
     144             : 
     145             :     status_t err;
     146           0 :     if ((err = findSampleTime(sampleIndex, &mCurrentSampleTime)) != OK) {
     147           0 :         ALOGE("findSampleTime return error");
     148           0 :         return err;
     149             :     }
     150             : 
     151             :     // mTTSDuration is set by findSampleTime()
     152           0 :     mCurrentSampleDuration = mTTSDuration;
     153           0 :     mCurrentSampleDecodeTime = mTTSSampleTime + mTTSDuration * (sampleIndex -
     154           0 :         mTTSSampleIndex);
     155           0 :     mCurrentSampleIndex = sampleIndex;
     156             : 
     157           0 :     mInitialized = true;
     158             : 
     159           0 :     return OK;
     160             : }
     161             : 
     162           0 : status_t SampleIterator::findChunkRange(uint32_t sampleIndex) {
     163           0 :     CHECK(sampleIndex >= mFirstChunkSampleIndex);
     164             : 
     165           0 :     while (sampleIndex >= mStopChunkSampleIndex) {
     166           0 :         if (mSampleToChunkIndex == mTable->mNumSampleToChunkOffsets) {
     167           0 :             return ERROR_OUT_OF_RANGE;
     168             :         }
     169             : 
     170           0 :         mFirstChunkSampleIndex = mStopChunkSampleIndex;
     171             : 
     172             :         const SampleTable::SampleToChunkEntry *entry =
     173           0 :             &mTable->mSampleToChunkEntries[mSampleToChunkIndex];
     174             : 
     175           0 :         mFirstChunk = entry->startChunk;
     176           0 :         mSamplesPerChunk = entry->samplesPerChunk;
     177           0 :         mChunkDesc = entry->chunkDesc;
     178             : 
     179           0 :         if (mSampleToChunkIndex + 1 < mTable->mNumSampleToChunkOffsets) {
     180           0 :             mStopChunk = entry[1].startChunk;
     181             : 
     182           0 :             mStopChunkSampleIndex =
     183           0 :                 mFirstChunkSampleIndex
     184           0 :                     + (mStopChunk - mFirstChunk) * mSamplesPerChunk;
     185           0 :         } else if (mSamplesPerChunk) {
     186           0 :             mStopChunk = 0xffffffff;
     187           0 :             mStopChunkSampleIndex = 0xffffffff;
     188             :         }
     189             : 
     190           0 :         ++mSampleToChunkIndex;
     191             :     }
     192             : 
     193           0 :     return OK;
     194             : }
     195             : 
     196           0 : status_t SampleIterator::getChunkOffset(uint32_t chunk, off64_t *offset) {
     197           0 :     *offset = 0;
     198             : 
     199           0 :     if (chunk >= mTable->mNumChunkOffsets) {
     200           0 :         return ERROR_OUT_OF_RANGE;
     201             :     }
     202             : 
     203           0 :     if (mTable->mChunkOffsetType == SampleTable::kChunkOffsetType32) {
     204             :         uint32_t offset32;
     205             : 
     206           0 :         if (mTable->mDataSource->readAt(
     207           0 :                     mTable->mChunkOffsetOffset + 8 + 4 * chunk,
     208             :                     &offset32,
     209           0 :                     sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
     210           0 :             return ERROR_IO;
     211             :         }
     212             : 
     213           0 :         *offset = ntohl(offset32);
     214             :     } else {
     215           0 :         CHECK_EQ(mTable->mChunkOffsetType, SampleTable::kChunkOffsetType64);
     216             : 
     217             :         uint64_t offset64;
     218           0 :         if (mTable->mDataSource->readAt(
     219           0 :                     mTable->mChunkOffsetOffset + 8 + 8 * chunk,
     220             :                     &offset64,
     221           0 :                     sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
     222           0 :             return ERROR_IO;
     223             :         }
     224             : 
     225           0 :         *offset = ntoh64(offset64);
     226             :     }
     227             : 
     228           0 :     return OK;
     229             : }
     230             : 
     231           0 : status_t SampleIterator::getSampleSizeDirect(
     232             :         uint32_t sampleIndex, size_t *size) {
     233           0 :     *size = 0;
     234             : 
     235           0 :     if (sampleIndex >= mTable->mNumSampleSizes) {
     236           0 :         return ERROR_OUT_OF_RANGE;
     237             :     }
     238             : 
     239           0 :     if (mTable->mDefaultSampleSize > 0) {
     240           0 :         *size = mTable->mDefaultSampleSize;
     241           0 :         return OK;
     242             :     }
     243             : 
     244           0 :     switch (mTable->mSampleSizeFieldSize) {
     245             :         case 32:
     246             :         {
     247           0 :             if (mTable->mDataSource->readAt(
     248           0 :                         mTable->mSampleSizeOffset + 12 + 4 * sampleIndex,
     249           0 :                         size, sizeof(*size)) < (ssize_t)sizeof(*size)) {
     250           0 :                 return ERROR_IO;
     251             :             }
     252             : 
     253           0 :             *size = ntohl(*size);
     254           0 :             break;
     255             :         }
     256             : 
     257             :         case 16:
     258             :         {
     259             :             uint16_t x;
     260           0 :             if (mTable->mDataSource->readAt(
     261           0 :                         mTable->mSampleSizeOffset + 12 + 2 * sampleIndex,
     262           0 :                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
     263           0 :                 return ERROR_IO;
     264             :             }
     265             : 
     266           0 :             *size = ntohs(x);
     267           0 :             break;
     268             :         }
     269             : 
     270             :         case 8:
     271             :         {
     272             :             uint8_t x;
     273           0 :             if (mTable->mDataSource->readAt(
     274           0 :                         mTable->mSampleSizeOffset + 12 + sampleIndex,
     275           0 :                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
     276           0 :                 return ERROR_IO;
     277             :             }
     278             : 
     279           0 :             *size = x;
     280           0 :             break;
     281             :         }
     282             : 
     283             :         default:
     284             :         {
     285           0 :             CHECK_EQ(mTable->mSampleSizeFieldSize, 4);
     286             : 
     287             :             uint8_t x;
     288           0 :             if (mTable->mDataSource->readAt(
     289           0 :                         mTable->mSampleSizeOffset + 12 + sampleIndex / 2,
     290           0 :                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
     291           0 :                 return ERROR_IO;
     292             :             }
     293             : 
     294           0 :             *size = (sampleIndex & 1) ? x & 0x0f : x >> 4;
     295           0 :             break;
     296             :         }
     297             :     }
     298             : 
     299           0 :     return OK;
     300             : }
     301             : 
     302           0 : status_t SampleIterator::findSampleTime(
     303             :         uint32_t sampleIndex, uint32_t *time) {
     304           0 :     if (sampleIndex >= mTable->mNumSampleSizes) {
     305           0 :         return ERROR_OUT_OF_RANGE;
     306             :     }
     307             : 
     308           0 :     while (sampleIndex >= mTTSSampleIndex + mTTSCount) {
     309           0 :         if (mTimeToSampleIndex == mTable->mTimeToSampleCount) {
     310           0 :             return ERROR_OUT_OF_RANGE;
     311             :         }
     312             : 
     313           0 :         mTTSSampleIndex += mTTSCount;
     314           0 :         mTTSSampleTime += mTTSCount * mTTSDuration;
     315             : 
     316           0 :         mTTSCount = mTable->mTimeToSample[2 * mTimeToSampleIndex];
     317           0 :         mTTSDuration = mTable->mTimeToSample[2 * mTimeToSampleIndex + 1];
     318             : 
     319           0 :         ++mTimeToSampleIndex;
     320             :     }
     321             : 
     322           0 :     *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
     323             : 
     324           0 :     *time += mTable->getCompositionTimeOffset(sampleIndex);
     325             : 
     326           0 :     return OK;
     327             : }
     328             : 
     329             : }  // namespace stagefright
     330             : 
     331             : #undef LOG_TAG

Generated by: LCOV version 1.13