Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (C) 2012 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_TAG "TimedTextSRTSource_test"
     18 #include <utils/Log.h>
     19 
     20 #include <gtest/gtest.h>
     21 
     22 #include <binder/Parcel.h>
     23 #include <media/stagefright/foundation/AString.h>
     24 #include <media/stagefright/DataSource.h>
     25 #include <media/stagefright/MediaErrors.h>
     26 #include <utils/misc.h>
     27 
     28 #include <TimedTextSource.h>
     29 #include <TimedTextSRTSource.h>
     30 
     31 namespace android {
     32 namespace test {
     33 
     34 static const int kSecToUsec = 1000000;
     35 static const int kSecToMsec = 1000;
     36 static const int kMsecToUsec = 1000;
     37 
     38 /* SRT format (http://en.wikipedia.org/wiki/SubRip)
     39  *   Subtitle number
     40  *   Start time --> End time
     41  *   Text of subtitle (one or more lines)
     42  *   Blank lines
     43  */
     44 static const char *kSRTString =
     45     "1\n00:00:1,000 --> 00:00:1,500\n1\n\n"
     46     "2\n00:00:2,000 --> 00:00:2,500\n2\n\n"
     47     "3\n00:00:3,000 --> 00:00:3,500\n3\n\n"
     48     "4\n00:00:4,000 --> 00:00:4,500\n4\n\n"
     49     "5\n00:00:5,000 --> 00:00:5,500\n5\n\n"
     50     // edge case : previos end time = next start time
     51     "6\n00:00:5,500 --> 00:00:5,800\n6\n\n"
     52     "7\n00:00:5,800 --> 00:00:6,000\n7\n\n"
     53     "8\n00:00:6,000 --> 00:00:7,000\n8\n\n";
     54 
     55 class SRTDataSourceStub : public DataSource {
     56 public:
     57     SRTDataSourceStub(const char *data, size_t size) :
     58         mData(data), mSize(size) {}
     59     virtual ~SRTDataSourceStub() {}
     60 
     61     virtual status_t initCheck() const {
     62         return OK;
     63     }
     64 
     65     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
     66         if (offset >= mSize) return 0;
     67 
     68         ssize_t avail = mSize - offset;
     69         if (avail > size) {
     70             avail = size;
     71         }
     72         memcpy(data, mData + offset, avail);
     73         return avail;
     74     }
     75 
     76 private:
     77     const char *mData;
     78     size_t mSize;
     79 };
     80 
     81 class TimedTextSRTSourceTest : public testing::Test {
     82 protected:
     83     void SetUp() {
     84         sp<DataSource> stub= new SRTDataSourceStub(
     85                 kSRTString,
     86                 strlen(kSRTString));
     87         mSource = new TimedTextSRTSource(stub);
     88         mSource->start();
     89     }
     90 
     91     void CheckStartTimeMs(const Parcel& parcel, int32_t timeMs) {
     92         int32_t intval;
     93         parcel.setDataPosition(8);
     94         parcel.readInt32(&intval);
     95         EXPECT_EQ(timeMs, intval);
     96     }
     97 
     98     void CheckDataEquals(const Parcel& parcel, const char* content) {
     99         int32_t intval;
    100         parcel.setDataPosition(16);
    101         parcel.readInt32(&intval);
    102         parcel.setDataPosition(24);
    103         const char* data = (const char*) parcel.readInplace(intval);
    104 
    105         int32_t content_len = strlen(content);
    106         EXPECT_EQ(content_len, intval);
    107         EXPECT_TRUE(strncmp(data, content, content_len) == 0);
    108     }
    109 
    110     sp<TimedTextSource> mSource;
    111     int64_t startTimeUs;
    112     int64_t endTimeUs;
    113     Parcel parcel;
    114     AString subtitle;
    115     status_t err;
    116 };
    117 
    118 TEST_F(TimedTextSRTSourceTest, readAll) {
    119     for (int i = 1; i <= 5; i++) {
    120         err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
    121         EXPECT_EQ(OK, err);
    122         CheckStartTimeMs(parcel, i * kSecToMsec);
    123         subtitle = StringPrintf("%d\n\n", i);
    124         CheckDataEquals(parcel, subtitle.c_str());
    125     }
    126     // read edge cases
    127     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
    128     EXPECT_EQ(OK, err);
    129     CheckStartTimeMs(parcel, 5500);
    130     subtitle = StringPrintf("6\n\n");
    131     CheckDataEquals(parcel, subtitle.c_str());
    132 
    133     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
    134     EXPECT_EQ(OK, err);
    135     CheckStartTimeMs(parcel, 5800);
    136     subtitle = StringPrintf("7\n\n");
    137     CheckDataEquals(parcel, subtitle.c_str());
    138 
    139     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
    140     EXPECT_EQ(OK, err);
    141     CheckStartTimeMs(parcel, 6000);
    142     subtitle = StringPrintf("8\n\n");
    143     CheckDataEquals(parcel, subtitle.c_str());
    144 
    145     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
    146     EXPECT_EQ(ERROR_END_OF_STREAM, err);
    147 }
    148 
    149 TEST_F(TimedTextSRTSourceTest, seekTimeIsEarlierThanFirst) {
    150     MediaSource::ReadOptions options;
    151     options.setSeekTo(500, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    152     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    153     EXPECT_EQ(OK, err);
    154     EXPECT_EQ(1 * kSecToUsec, startTimeUs);
    155     CheckStartTimeMs(parcel, 1 * kSecToMsec);
    156 }
    157 
    158 TEST_F(TimedTextSRTSourceTest, seekTimeIsLaterThanLast) {
    159     MediaSource::ReadOptions options;
    160     options.setSeekTo(7 * kSecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    161     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    162     EXPECT_EQ(ERROR_END_OF_STREAM, err);
    163 
    164     options.setSeekTo(8 * kSecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    165     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    166     EXPECT_EQ(ERROR_END_OF_STREAM, err);
    167 }
    168 
    169 TEST_F(TimedTextSRTSourceTest, seekTimeIsMatched) {
    170     for (int i = 1; i <= 5; i++) {
    171         MediaSource::ReadOptions options;
    172         options.setSeekTo(i * kSecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    173         err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    174         EXPECT_EQ(OK, err);
    175         EXPECT_EQ(i * kSecToUsec, startTimeUs);
    176 
    177         options.setSeekTo(i * kSecToUsec + 100, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    178         err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    179         EXPECT_EQ(OK, err);
    180         EXPECT_EQ(i * kSecToUsec, startTimeUs);
    181     }
    182 }
    183 
    184 TEST_F(TimedTextSRTSourceTest, seekTimeInBetweenTwo) {
    185     for (int i = 1; i <= 4; i++) {
    186         MediaSource::ReadOptions options;
    187         options.setSeekTo(i * kSecToUsec + 500000, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    188         err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    189         EXPECT_EQ(OK, err);
    190         EXPECT_EQ((i + 1) * kSecToUsec, startTimeUs);
    191 
    192         options.setSeekTo(i * kSecToUsec + 600000, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    193         err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    194         EXPECT_EQ(OK, err);
    195         EXPECT_EQ((i + 1) * kSecToUsec, startTimeUs);
    196     }
    197 }
    198 
    199 TEST_F(TimedTextSRTSourceTest, checkEdgeCase) {
    200     MediaSource::ReadOptions options;
    201     options.setSeekTo(5500 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    202     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    203     EXPECT_EQ(OK, err);
    204     EXPECT_EQ(5500 * kMsecToUsec, startTimeUs);
    205     subtitle = StringPrintf("6\n\n");
    206     CheckDataEquals(parcel, subtitle.c_str());
    207 
    208     options.setSeekTo(5800 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    209     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    210     EXPECT_EQ(OK, err);
    211     EXPECT_EQ(5800 * kMsecToUsec, startTimeUs);
    212     subtitle = StringPrintf("7\n\n");
    213     CheckDataEquals(parcel, subtitle.c_str());
    214 
    215     options.setSeekTo(6000 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
    216     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
    217     EXPECT_EQ(OK, err);
    218     EXPECT_EQ(6000 * kMsecToUsec, startTimeUs);
    219     subtitle = StringPrintf("8\n\n");
    220     CheckDataEquals(parcel, subtitle.c_str());
    221 }
    222 
    223 }  // namespace test
    224 }  // namespace android
    225