1e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber/* 2e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * 4e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * you may not use this file except in compliance with the License. 6e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * You may obtain a copy of the License at 7e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * 8e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * 10e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * Unless required by applicable law or agreed to in writing, software 11e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * See the License for the specific language governing permissions and 14e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber * limitations under the License. 15e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber */ 16e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 17ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber//#define LOG_NDEBUG 0 18ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber#define LOG_TAG "M3UParser" 19ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber#include <utils/Log.h> 20ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber 2114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include "M3UParser.h" 22dcb89b3b505522efde173c105a851c412f947178Chong Zhang#include <binder/Parcel.h> 2314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#include <cutils/properties.h> 240a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber#include <media/stagefright/foundation/ADebug.h> 25e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber#include <media/stagefright/foundation/AMessage.h> 26404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang#include <media/stagefright/MediaDefs.h> 27e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber#include <media/stagefright/MediaErrors.h> 28ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih#include <media/stagefright/Utils.h> 29dcb89b3b505522efde173c105a851c412f947178Chong Zhang#include <media/mediaplayer.h> 30e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 31e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Hubernamespace android { 32e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 3314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstruct M3UParser::MediaGroup : public RefBase { 3414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber enum Type { 3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TYPE_AUDIO, 3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TYPE_VIDEO, 3714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TYPE_SUBS, 3899cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang TYPE_CC, 3914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber }; 4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber enum FlagBits { 4214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FLAG_AUTOSELECT = 1, 4314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FLAG_DEFAULT = 2, 4414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FLAG_FORCED = 4, 4514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FLAG_HAS_LANGUAGE = 8, 4614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber FLAG_HAS_URI = 16, 4714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber }; 4814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 4914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber MediaGroup(Type type); 5014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber Type type() const; 5214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber status_t addMedia( 5414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *name, 5514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *uri, 5614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *language, 5714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t flags); 5814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 5914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool getActiveURI(AString *uri) const; 6014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber void pickRandomMediaItems(); 62dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t selectTrack(size_t index, bool select); 63dcb89b3b505522efde173c105a851c412f947178Chong Zhang size_t countTracks() const; 64404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang sp<AMessage> getTrackInfo(size_t index) const; 6514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberprotected: 6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber virtual ~MediaGroup(); 6814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberprivate: 7089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 7189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih friend struct M3UParser; 7289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 7314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber struct Media { 7414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString mName; 7514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString mURI; 7614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString mLanguage; 7714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t mFlags; 7814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber }; 7914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber Type mType; 8114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber Vector<Media> mMediaItems; 8214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t mSelectedIndex; 8414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MediaGroup); 8614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}; 8714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 8814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberM3UParser::MediaGroup::MediaGroup(Type type) 8914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber : mType(type), 9014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex(-1) { 9114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 9214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 9314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberM3UParser::MediaGroup::~MediaGroup() { 9414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 9514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 9614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberM3UParser::MediaGroup::Type M3UParser::MediaGroup::type() const { 9714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return mType; 9814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 9914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 10014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t M3UParser::MediaGroup::addMedia( 10114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *name, 10214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *uri, 10314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const char *language, 10414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t flags) { 10514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mMediaItems.push(); 10614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber Media &item = mMediaItems.editItemAt(mMediaItems.size() - 1); 10714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 10814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mName = name; 10914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 11014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (uri) { 11114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mURI = uri; 11214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 11314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 11414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (language) { 11514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mLanguage = language; 11614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 11714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 11814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber item.mFlags = flags; 11914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 12014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 12114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 12214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 12314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid M3UParser::MediaGroup::pickRandomMediaItems() { 12414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#if 1 12514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber switch (mType) { 12614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case TYPE_AUDIO: 12714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 12814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char value[PROPERTY_VALUE_MAX]; 12914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (property_get("media.httplive.audio-index", value, NULL)) { 13014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char *end; 13114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex = strtoul(value, &end, 10); 13214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK(end > value && *end == '\0'); 13314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 13484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber if (mSelectedIndex >= (ssize_t)mMediaItems.size()) { 13514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex = mMediaItems.size() - 1; 13614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 13714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 13814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex = 0; 13914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 14014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 14114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 14214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 14314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case TYPE_VIDEO: 14414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 14514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex = 0; 14614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 14714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 14814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 14914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber case TYPE_SUBS: 15014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber { 15114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex = -1; 15214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber break; 15314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 15414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 15514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber default: 15614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber TRESPASS(); 15714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 15814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#else 15914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mSelectedIndex = (rand() * mMediaItems.size()) / RAND_MAX; 16014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber#endif 16114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 16214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 163dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t M3UParser::MediaGroup::selectTrack(size_t index, bool select) { 164309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (mType != TYPE_SUBS && mType != TYPE_AUDIO) { 165309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih ALOGE("only select subtitile/audio tracks for now!"); 166dcb89b3b505522efde173c105a851c412f947178Chong Zhang return INVALID_OPERATION; 167dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 168dcb89b3b505522efde173c105a851c412f947178Chong Zhang 169dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (select) { 170dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (index >= mMediaItems.size()) { 171b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGE("track %zu does not exist", index); 172dcb89b3b505522efde173c105a851c412f947178Chong Zhang return INVALID_OPERATION; 173dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 17484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber if (mSelectedIndex == (ssize_t)index) { 175b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGE("track %zu already selected", index); 176dcb89b3b505522efde173c105a851c412f947178Chong Zhang return BAD_VALUE; 177dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 178b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("selected track %zu", index); 179dcb89b3b505522efde173c105a851c412f947178Chong Zhang mSelectedIndex = index; 180dcb89b3b505522efde173c105a851c412f947178Chong Zhang } else { 18184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber if (mSelectedIndex != (ssize_t)index) { 182b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGE("track %zu is not selected", index); 183dcb89b3b505522efde173c105a851c412f947178Chong Zhang return BAD_VALUE; 184dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 185b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("unselected track %zu", index); 186dcb89b3b505522efde173c105a851c412f947178Chong Zhang mSelectedIndex = -1; 187dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 188dcb89b3b505522efde173c105a851c412f947178Chong Zhang 189dcb89b3b505522efde173c105a851c412f947178Chong Zhang return OK; 190dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 191dcb89b3b505522efde173c105a851c412f947178Chong Zhang 192404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t M3UParser::MediaGroup::countTracks() const { 193404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang return mMediaItems.size(); 194404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 195dcb89b3b505522efde173c105a851c412f947178Chong Zhang 196404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> M3UParser::MediaGroup::getTrackInfo(size_t index) const { 197404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang if (index >= mMediaItems.size()) { 198404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang return NULL; 199404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang } 200a911f51c21430ac92f1d796b2338878fd98382e9Chong Zhang 201404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang sp<AMessage> format = new AMessage(); 202404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 203404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang int32_t trackType; 204404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang if (mType == TYPE_AUDIO) { 205404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang trackType = MEDIA_TRACK_TYPE_AUDIO; 206404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang } else if (mType == TYPE_VIDEO) { 207404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang trackType = MEDIA_TRACK_TYPE_VIDEO; 208404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang } else if (mType == TYPE_SUBS) { 209404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang trackType = MEDIA_TRACK_TYPE_SUBTITLE; 210404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang } else { 211404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang trackType = MEDIA_TRACK_TYPE_UNKNOWN; 212404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang } 213404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang format->setInt32("type", trackType); 214404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 215404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang const Media &item = mMediaItems.itemAt(index); 216404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang const char *lang = item.mLanguage.empty() ? "und" : item.mLanguage.c_str(); 217404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang format->setString("language", lang); 218404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang 219404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang if (mType == TYPE_SUBS) { 220404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang // TO-DO: pass in a MediaFormat instead 221404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang format->setString("mime", MEDIA_MIMETYPE_TEXT_VTT); 222404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang format->setInt32("auto", !!(item.mFlags & MediaGroup::FLAG_AUTOSELECT)); 223404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang format->setInt32("default", !!(item.mFlags & MediaGroup::FLAG_DEFAULT)); 224404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang format->setInt32("forced", !!(item.mFlags & MediaGroup::FLAG_FORCED)); 225dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 226dcb89b3b505522efde173c105a851c412f947178Chong Zhang 227404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang return format; 228dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 229dcb89b3b505522efde173c105a851c412f947178Chong Zhang 23014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool M3UParser::MediaGroup::getActiveURI(AString *uri) const { 23114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mMediaItems.size(); ++i) { 23214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (mSelectedIndex >= 0 && i == (size_t)mSelectedIndex) { 23314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const Media &item = mMediaItems.itemAt(i); 23414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 23514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber *uri = item.mURI; 23614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return true; 23714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 23814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 23914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 24014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return false; 24114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 24214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 24314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber//////////////////////////////////////////////////////////////////////////////// 24414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 245e71d10e7ad55ccbcb0756c007caef1c959090384Andreas HuberM3UParser::M3UParser( 246e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const char *baseURI, const void *data, size_t size) 247e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber : mInitCheck(NO_INIT), 248e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mBaseURI(baseURI), 249e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsExtM3U(false), 250bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mIsVariantPlaylist(false), 251b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber mIsComplete(false), 252dcb89b3b505522efde173c105a851c412f947178Chong Zhang mIsEvent(false), 253978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mFirstSeqNumber(-1), 254978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mLastSeqNumber(-1), 255978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mTargetDurationUs(-1ll), 256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuitySeq(0), 257c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang mDiscontinuityCount(0), 258dcb89b3b505522efde173c105a851c412f947178Chong Zhang mSelectedIndex(-1) { 259e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mInitCheck = parse(data, size); 260e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 261e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 262e71d10e7ad55ccbcb0756c007caef1c959090384Andreas HuberM3UParser::~M3UParser() { 263e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 264e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 265e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::initCheck() const { 266e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mInitCheck; 267e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 268e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 269e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberbool M3UParser::isExtM3U() const { 270e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mIsExtM3U; 271e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 272e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 273e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberbool M3UParser::isVariantPlaylist() const { 274e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mIsVariantPlaylist; 275e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 276e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 277bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huberbool M3UParser::isComplete() const { 278bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber return mIsComplete; 279bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber} 280bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 281b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huberbool M3UParser::isEvent() const { 282b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber return mIsEvent; 283b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber} 284b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 285309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shihsize_t M3UParser::getDiscontinuitySeq() const { 286309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return mDiscontinuitySeq; 287309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih} 288309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 289978449984366946a2e5c9f7cf350746f4306caf8Chong Zhangint64_t M3UParser::getTargetDuration() const { 290978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return mTargetDurationUs; 291978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang} 292978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 293978449984366946a2e5c9f7cf350746f4306caf8Chong Zhangint32_t M3UParser::getFirstSeqNumber() const { 294978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return mFirstSeqNumber; 295978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang} 296978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 297978449984366946a2e5c9f7cf350746f4306caf8Chong Zhangvoid M3UParser::getSeqNumberRange(int32_t *firstSeq, int32_t *lastSeq) const { 298978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *firstSeq = mFirstSeqNumber; 299978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang *lastSeq = mLastSeqNumber; 300978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang} 301978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 302e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Hubersp<AMessage> M3UParser::meta() { 303e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mMeta; 304e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 305e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 306e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Hubersize_t M3UParser::size() { 307e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mItems.size(); 308e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 309e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 310e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberbool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) { 3110f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber if (uri) { 3120f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber uri->clear(); 3130f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber } 3140f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber 3150f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber if (meta) { 3160f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber *meta = NULL; 3170f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber } 318e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 319e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (index >= mItems.size()) { 320e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return false; 321e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 322e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 3230f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber if (uri) { 3240f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber *uri = mItems.itemAt(index).mURI; 3250f30bd90272c818aa37c0bb22d22eaa7d3689879Andreas Huber } 326e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 327e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (meta) { 328e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *meta = mItems.itemAt(index).mMeta; 329e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 330e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 331e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return true; 332e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 333e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 33414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Hubervoid M3UParser::pickRandomMediaItems() { 33514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber for (size_t i = 0; i < mMediaGroups.size(); ++i) { 33614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mMediaGroups.valueAt(i)->pickRandomMediaItems(); 33714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 33814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 33914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 340dcb89b3b505522efde173c105a851c412f947178Chong Zhangstatus_t M3UParser::selectTrack(size_t index, bool select) { 341dcb89b3b505522efde173c105a851c412f947178Chong Zhang for (size_t i = 0, ii = index; i < mMediaGroups.size(); ++i) { 342dcb89b3b505522efde173c105a851c412f947178Chong Zhang sp<MediaGroup> group = mMediaGroups.valueAt(i); 343dcb89b3b505522efde173c105a851c412f947178Chong Zhang size_t tracks = group->countTracks(); 344dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (ii < tracks) { 345dcb89b3b505522efde173c105a851c412f947178Chong Zhang status_t err = group->selectTrack(ii, select); 346dcb89b3b505522efde173c105a851c412f947178Chong Zhang if (err == OK) { 347dcb89b3b505522efde173c105a851c412f947178Chong Zhang mSelectedIndex = select ? index : -1; 348dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 349dcb89b3b505522efde173c105a851c412f947178Chong Zhang return err; 350dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 351dcb89b3b505522efde173c105a851c412f947178Chong Zhang ii -= tracks; 352dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 353dcb89b3b505522efde173c105a851c412f947178Chong Zhang return INVALID_OPERATION; 354dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 355dcb89b3b505522efde173c105a851c412f947178Chong Zhang 356404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsize_t M3UParser::getTrackCount() const { 357dcb89b3b505522efde173c105a851c412f947178Chong Zhang size_t trackCount = 0; 358dcb89b3b505522efde173c105a851c412f947178Chong Zhang for (size_t i = 0; i < mMediaGroups.size(); ++i) { 359dcb89b3b505522efde173c105a851c412f947178Chong Zhang trackCount += mMediaGroups.valueAt(i)->countTracks(); 360dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 361404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang return trackCount; 362404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang} 363dcb89b3b505522efde173c105a851c412f947178Chong Zhang 364404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhangsp<AMessage> M3UParser::getTrackInfo(size_t index) const { 365404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang for (size_t i = 0, ii = index; i < mMediaGroups.size(); ++i) { 366404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang sp<MediaGroup> group = mMediaGroups.valueAt(i); 367404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang size_t tracks = group->countTracks(); 368404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang if (ii < tracks) { 369404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang return group->getTrackInfo(ii); 370404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang } 371404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang ii -= tracks; 372dcb89b3b505522efde173c105a851c412f947178Chong Zhang } 373404fced9bfa8fa423ee210a271ca051ffd1bec13Chong Zhang return NULL; 374dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 375dcb89b3b505522efde173c105a851c412f947178Chong Zhang 376dcb89b3b505522efde173c105a851c412f947178Chong Zhangssize_t M3UParser::getSelectedIndex() const { 377dcb89b3b505522efde173c105a851c412f947178Chong Zhang return mSelectedIndex; 378dcb89b3b505522efde173c105a851c412f947178Chong Zhang} 379dcb89b3b505522efde173c105a851c412f947178Chong Zhang 38089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shihssize_t M3UParser::getSelectedTrack(media_track_type type) const { 38189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih MediaGroup::Type groupType; 38289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih switch (type) { 38389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih case MEDIA_TRACK_TYPE_VIDEO: 38489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih groupType = MediaGroup::TYPE_VIDEO; 38589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih break; 38689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 38789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih case MEDIA_TRACK_TYPE_AUDIO: 38889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih groupType = MediaGroup::TYPE_AUDIO; 38989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih break; 39089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 39189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih case MEDIA_TRACK_TYPE_SUBTITLE: 39289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih groupType = MediaGroup::TYPE_SUBS; 39389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih break; 39489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 39589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih default: 39689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 39789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 39889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 39989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih for (size_t i = 0, ii = 0; i < mMediaGroups.size(); ++i) { 40089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih sp<MediaGroup> group = mMediaGroups.valueAt(i); 40189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih size_t tracks = group->countTracks(); 40289bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih if (groupType != group->mType) { 40389bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih ii += tracks; 40489bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } else if (group->mSelectedIndex >= 0) { 40589bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return ii + group->mSelectedIndex; 40689bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 40789bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih } 40889bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 40989bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih return -1; 41089bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih} 41189bf2525c5b57f17260de5b00c5f3f78ac4b881eRobert Shih 41214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberbool M3UParser::getTypeURI(size_t index, const char *key, AString *uri) const { 41314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!mIsVariantPlaylist) { 414d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (uri != NULL) { 415d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *uri = mBaseURI; 416d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 41714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 41814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // Assume media without any more specific attribute contains 41914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber // audio and video, but no subtitles. 42014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return !strcmp("audio", key) || !strcmp("video", key); 42114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 42214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 42314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_LT(index, mItems.size()); 42414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 42514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<AMessage> meta = mItems.itemAt(index).mMeta; 42614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 42714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupID; 42814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!meta->findString(key, &groupID)) { 429d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (uri != NULL) { 430d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *uri = mItems.itemAt(index).mURI; 431d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 43214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 433ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih AString codecs; 434ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!meta->findString("codecs", &codecs)) { 435ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // Assume media without any more specific attribute contains 436ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // audio and video, but no subtitles. 437ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return !strcmp("audio", key) || !strcmp("video", key); 438ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } else { 439ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // Split the comma separated list of codecs. 440ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih size_t offset = 0; 441ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih ssize_t commaPos = -1; 442ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih codecs.append(','); 443ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih while ((commaPos = codecs.find(",", offset)) >= 0) { 444ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih AString codec(codecs, offset, commaPos - offset); 4451ac1638077277de52d1dd4c54db71e67753f1960Robert Shih codec.trim(); 446ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // return true only if a codec of type `key` ("audio"/"video") 447ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // is found. 448ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (codecIsType(codec, key)) { 449ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return true; 450ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 451ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih offset = commaPos + 1; 452ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 453ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 454ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 45514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 45614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 457d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // if uri == NULL, we're only checking if the type is present, 458d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // don't care about the active URI (or if there is an active one) 459d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (uri != NULL) { 460d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang sp<MediaGroup> group = mMediaGroups.valueFor(groupID); 461d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if (!group->getActiveURI(uri)) { 462d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return false; 463d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 46414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 465d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang if ((*uri).empty()) { 466d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang *uri = mItems.itemAt(index).mURI; 467d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 46814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 46914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 47014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return true; 47114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 47214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 473d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhangbool M3UParser::hasType(size_t index, const char *key) const { 474d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang return getTypeURI(index, key, NULL /* uri */); 475d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang} 476d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 477e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatic bool MakeURL(const char *baseURL, const char *url, AString *out) { 478e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->clear(); 479e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 4802a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (strncasecmp("http://", baseURL, 7) 481df42f949c8bd05b81d94633767514fff88f52062Andreas Huber && strncasecmp("https://", baseURL, 8) 4822a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber && strncasecmp("file://", baseURL, 7)) { 483e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber // Base URL must be absolute 484e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return false; 485e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 486a8454c29b15748964b5eb556d1e23fbb1ee19cebLajos Molnar const size_t schemeEnd = (strstr(baseURL, "//") - baseURL) + 2; 487a8454c29b15748964b5eb556d1e23fbb1ee19cebLajos Molnar CHECK(schemeEnd == 7 || schemeEnd == 8); 488e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 489df42f949c8bd05b81d94633767514fff88f52062Andreas Huber if (!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8)) { 490e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber // "url" is already an absolute URL, ignore base URL. 491e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->setTo(url); 492ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber 4933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str()); 494ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber 495e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return true; 496e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 497e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 498d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber if (url[0] == '/') { 499d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber // URL is an absolute path. 500d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber 501d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber char *protocolEnd = strstr(baseURL, "//") + 2; 502d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber char *pathStart = strchr(protocolEnd, '/'); 503e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 504d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber if (pathStart != NULL) { 505d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber out->setTo(baseURL, pathStart - baseURL); 506e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else { 507e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->setTo(baseURL); 508e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 509e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 510e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->append(url); 511d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber } else { 512d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber // URL is a relative path 513d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber 5148883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo // Check for a possible query string 5158883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo const char *qsPos = strchr(baseURL, '?'); 5168883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo size_t end; 5178883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo if (qsPos != NULL) { 5188883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo end = qsPos - baseURL; 519d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber } else { 5208883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo end = strlen(baseURL); 5218883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo } 5228883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo // Check for the last slash before a potential query string 523e175d77bb610675ba2f70f24449189995ddeaf5bMarco Nelissen for (ssize_t pos = end - 1; pos >= 0; pos--) { 5248883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo if (baseURL[pos] == '/') { 5258883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo end = pos; 5268883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo break; 527d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber } 5288883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo } 529d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber 5308883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo // Check whether the found slash actually is part of the path 5318883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo // and not part of the "http://". 532a8454c29b15748964b5eb556d1e23fbb1ee19cebLajos Molnar if (end >= schemeEnd) { 5338883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo out->setTo(baseURL, end); 5348883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo } else { 5358883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo out->setTo(baseURL); 536d6a46a6bda23667e06ee5ccca3781e407c7d1204Andreas Huber } 5378883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo 5388883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo out->append("/"); 5398883a38a308fb02a653c990118ec7931a47b749bMartin Storsjo out->append(url); 540e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 541e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 5423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str()); 543ac13b81c590386b3a42e381b31d7614ca53b79c5Andreas Huber 544e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return true; 545e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 546e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 547e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::parse(const void *_data, size_t size) { 548e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber int32_t lineNo = 0; 549e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 550e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber sp<AMessage> itemMeta; 551e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 552e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const char *data = (const char *)_data; 553e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber size_t offset = 0; 5542aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber uint64_t segmentRangeOffset = 0; 555e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber while (offset < size) { 556e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber size_t offsetLF = offset; 557e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber while (offsetLF < size && data[offsetLF] != '\n') { 558e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ++offsetLF; 559e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 560e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 561e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber AString line; 562e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (offsetLF > offset && data[offsetLF - 1] == '\r') { 563e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber line.setTo(&data[offset], offsetLF - offset - 1); 564e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else { 565e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber line.setTo(&data[offset], offsetLF - offset); 566e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 567e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 568df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block // ALOGI("#%s#", line.c_str()); 5692a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 5702a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (line.empty()) { 5712a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber offset = offsetLF + 1; 5722a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 5732a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 574e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 575e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (lineNo == 0 && line == "#EXTM3U") { 576e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsExtM3U = true; 577e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 578e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 579e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsExtM3U) { 580e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber status_t err = OK; 581e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 582e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (line.startsWith("#EXT-X-TARGETDURATION")) { 583e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsVariantPlaylist) { 584e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 585e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 586e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber err = parseMetaData(line, &mMeta, "target-duration"); 587e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXT-X-MEDIA-SEQUENCE")) { 588e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsVariantPlaylist) { 589e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 590e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 591e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber err = parseMetaData(line, &mMeta, "media-sequence"); 592e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } else if (line.startsWith("#EXT-X-KEY")) { 593e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (mIsVariantPlaylist) { 594e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return ERROR_MALFORMED; 595e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 596decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber err = parseCipherInfo(line, &itemMeta, mBaseURI); 597bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber } else if (line.startsWith("#EXT-X-ENDLIST")) { 598bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mIsComplete = true; 599b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber } else if (line.startsWith("#EXT-X-PLAYLIST-TYPE:EVENT")) { 600b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber mIsEvent = true; 601e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXTINF")) { 602e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsVariantPlaylist) { 603e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 604e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 6059067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber err = parseMetaDataDuration(line, &itemMeta, "durationUs"); 6062a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } else if (line.startsWith("#EXT-X-DISCONTINUITY")) { 6072a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (mIsVariantPlaylist) { 6082a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return ERROR_MALFORMED; 6092a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 6102a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (itemMeta == NULL) { 6112a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber itemMeta = new AMessage; 6122a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 6132a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber itemMeta->setInt32("discontinuity", true); 614c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang ++mDiscontinuityCount; 615e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXT-X-STREAM-INF")) { 616e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mMeta != NULL) { 617e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 618e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 619e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsVariantPlaylist = true; 6202a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber err = parseStreamInf(line, &itemMeta); 6212aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } else if (line.startsWith("#EXT-X-BYTERANGE")) { 6222aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (mIsVariantPlaylist) { 6232aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 6242aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 6252aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6262aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber uint64_t length, offset; 6272aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber err = parseByteRange(line, segmentRangeOffset, &length, &offset); 6282aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6292aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (err == OK) { 6302aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (itemMeta == NULL) { 6312aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber itemMeta = new AMessage; 6322aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 6332aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6342aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber itemMeta->setInt64("range-offset", offset); 6352aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber itemMeta->setInt64("range-length", length); 6362aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6372aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber segmentRangeOffset = offset + length; 6382aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 63914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (line.startsWith("#EXT-X-MEDIA")) { 64014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber err = parseMedia(line); 641309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } else if (line.startsWith("#EXT-X-DISCONTINUITY-SEQUENCE")) { 642c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang if (mIsVariantPlaylist) { 643c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang return ERROR_MALFORMED; 644c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang } 645309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih size_t seq; 646309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih err = parseDiscontinuitySequence(line, &seq); 647309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (err == OK) { 648309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih mDiscontinuitySeq = seq; 649309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 650e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 651e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 652e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (err != OK) { 653e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return err; 654e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 655e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 656e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 657e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!line.startsWith("#")) { 658e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!mIsVariantPlaylist) { 6599067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber int64_t durationUs; 660e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (itemMeta == NULL 6619067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber || !itemMeta->findInt64("durationUs", &durationUs)) { 662e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 663e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 664d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemMeta->setInt32("discontinuity-sequence", 665d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mDiscontinuitySeq + mDiscontinuityCount); 666e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 667e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 668e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mItems.push(); 669e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber Item *item = &mItems.editItemAt(mItems.size() - 1); 670e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 671e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber CHECK(MakeURL(mBaseURI.c_str(), line.c_str(), &item->mURI)); 672e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 673e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber item->mMeta = itemMeta; 674e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 675e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber itemMeta.clear(); 676e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 677e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 678e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber offset = offsetLF + 1; 679e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ++lineNo; 680e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 681e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 682d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // error checking of all fields that's required to appear once 683978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // (currently only checking "target-duration"), and 684978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // initialization of playlist properties (eg. mTargetDurationUs) 685978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mIsVariantPlaylist) { 686978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t targetDurationSecs; 687978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mMeta == NULL || !mMeta->findInt32( 688978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang "target-duration", &targetDurationSecs)) { 689978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ALOGE("Media playlist missing #EXT-X-TARGETDURATION"); 690978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return ERROR_MALFORMED; 691978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 692978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mTargetDurationUs = targetDurationSecs * 1000000ll; 693978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 694978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mFirstSeqNumber = 0; 695978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mMeta != NULL) { 696978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mMeta->findInt32("media-sequence", &mFirstSeqNumber); 697978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 698978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mLastSeqNumber = mFirstSeqNumber + mItems.size() - 1; 699d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 700d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 701e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 702e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 703e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 704e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber// static 705e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::parseMetaData( 706e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const AString &line, sp<AMessage> *meta, const char *key) { 707e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ssize_t colonPos = line.find(":"); 708e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 709e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (colonPos < 0) { 710e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 711e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 712e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 713e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber int32_t x; 714e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber status_t err = ParseInt32(line.c_str() + colonPos + 1, &x); 715e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 716e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (err != OK) { 717e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return err; 718e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 719e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 720e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (meta->get() == NULL) { 721e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *meta = new AMessage; 722e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 723e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber (*meta)->setInt32(key, x); 724e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 725e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 726e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 727e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 728e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber// static 7299067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huberstatus_t M3UParser::parseMetaDataDuration( 7309067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber const AString &line, sp<AMessage> *meta, const char *key) { 7319067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber ssize_t colonPos = line.find(":"); 7329067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7339067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (colonPos < 0) { 7349067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return ERROR_MALFORMED; 7359067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 7369067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7379067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber double x; 7389067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber status_t err = ParseDouble(line.c_str() + colonPos + 1, &x); 7399067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7409067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (err != OK) { 7419067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return err; 7429067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 7439067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7449067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (meta->get() == NULL) { 7459067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber *meta = new AMessage; 7469067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 747abd5feeea499ee7337125223df4ea22cae19cd20Oscar Rydhé (*meta)->setInt64(key, (int64_t)(x * 1E6)); 7489067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7499067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return OK; 7509067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber} 7519067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 75214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// Find the next occurence of the character "what" at or after "offset", 75314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// but ignore occurences between quotation marks. 75414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// Return the index of the occurrence or -1 if not found. 75514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatic ssize_t FindNextUnquoted( 75614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &line, char what, size_t offset) { 75714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_NE((int)what, (int)'"'); 75814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 75914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool quoted = false; 76014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (offset < line.size()) { 76114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char c = line.c_str()[offset]; 76214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 76314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (c == '"') { 76414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber quoted = !quoted; 76514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (c == what && !quoted) { 76614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return offset; 76714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 76814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 76914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ++offset; 77014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 77114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 77214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return -1; 77314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 77414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7752a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huberstatus_t M3UParser::parseStreamInf( 77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &line, sp<AMessage> *meta) const { 7772a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t colonPos = line.find(":"); 7782a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7792a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (colonPos < 0) { 7802a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return ERROR_MALFORMED; 7812a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 7822a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7832a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber size_t offset = colonPos + 1; 7842a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7852a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber while (offset < line.size()) { 78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t end = FindNextUnquoted(line, ',', offset); 7872a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (end < 0) { 7882a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber end = line.size(); 7892a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 7902a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7912a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString attr(line, offset, end - offset); 7922a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber attr.trim(); 7932a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7942a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber offset = end + 1; 7952a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7962a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t equalPos = attr.find("="); 7972a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (equalPos < 0) { 7982a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 7992a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8002a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8012a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString key(attr, 0, equalPos); 8022a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber key.trim(); 8032a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8042a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 8052a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber val.trim(); 8062a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("key=%s value=%s", key.c_str(), val.c_str()); 8082a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8092a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (!strcasecmp("bandwidth", key.c_str())) { 8102a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const char *s = val.c_str(); 8112a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber char *end; 8122a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber unsigned long x = strtoul(s, &end, 10); 8132a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8142a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (end == s || *end != '\0') { 8152a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber // malformed 8162a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 8172a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8182a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8192a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (meta->get() == NULL) { 8202a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber *meta = new AMessage; 8212a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8222a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber (*meta)->setInt32("bandwidth", x); 823ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } else if (!strcasecmp("codecs", key.c_str())) { 824ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!isQuotedString(val)) { 825ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih ALOGE("Expected quoted string for %s attribute, " 826ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih "got '%s' instead.", 827ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih key.c_str(), val.c_str());; 828ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 829ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return ERROR_MALFORMED; 830ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 831ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 832ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih key.tolower(); 833ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih const AString &codecs = unquoteString(val); 8345154f98277922aba7103ac19529ecc00b1889c1eRobert Shih if (meta->get() == NULL) { 8355154f98277922aba7103ac19529ecc00b1889c1eRobert Shih *meta = new AMessage; 8365154f98277922aba7103ac19529ecc00b1889c1eRobert Shih } 837ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih (*meta)->setString(key.c_str(), codecs.c_str()); 838a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (!strcasecmp("resolution", key.c_str())) { 839a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang const char *s = val.c_str(); 840a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang char *end; 841a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang unsigned long width = strtoul(s, &end, 10); 842a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 843a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (end == s || *end != 'x') { 844a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang // malformed 845a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang continue; 846a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 847a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 848a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang s = end + 1; 849a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang unsigned long height = strtoul(s, &end, 10); 850a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 851a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (end == s || *end != '\0') { 852a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang // malformed 853a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang continue; 854a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 855a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 856a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->get() == NULL) { 857a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang *meta = new AMessage; 858a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 859a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang (*meta)->setInt32("width", width); 860a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang (*meta)->setInt32("height", height); 86114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("audio", key.c_str()) 86214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || !strcasecmp("video", key.c_str()) 86314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || !strcasecmp("subtitles", key.c_str())) { 864ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!isQuotedString(val)) { 86514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for %s attribute, " 86614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 86714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key.c_str(), val.c_str()); 86814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 86914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 87014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 8712a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 872ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih const AString &groupID = unquoteString(val); 87314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t groupIndex = mMediaGroups.indexOfKey(groupID); 8742a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 87514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupIndex < 0) { 87614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Undefined media group '%s' referenced in stream info.", 87714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupID.c_str()); 8780a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber 87914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 88014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 8810a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber 88214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key.tolower(); 8835154f98277922aba7103ac19529ecc00b1889c1eRobert Shih if (meta->get() == NULL) { 8845154f98277922aba7103ac19529ecc00b1889c1eRobert Shih *meta = new AMessage; 8855154f98277922aba7103ac19529ecc00b1889c1eRobert Shih } 88614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber (*meta)->setString(key.c_str(), groupID.c_str()); 8870a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber } 8880a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber } 8890a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber 89014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 8910a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber} 8920a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber 8932a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber// static 894e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huberstatus_t M3UParser::parseCipherInfo( 895decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber const AString &line, sp<AMessage> *meta, const AString &baseURI) { 896e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t colonPos = line.find(":"); 897e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 898e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (colonPos < 0) { 899e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return ERROR_MALFORMED; 900e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 901e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 902e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber size_t offset = colonPos + 1; 903e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 904e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber while (offset < line.size()) { 9050a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber ssize_t end = FindNextUnquoted(line, ',', offset); 906e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (end < 0) { 907e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber end = line.size(); 908e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 909e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 910e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString attr(line, offset, end - offset); 911e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber attr.trim(); 912e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 913e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber offset = end + 1; 914e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 915e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t equalPos = attr.find("="); 916e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (equalPos < 0) { 917e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber continue; 918e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 919e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 920e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString key(attr, 0, equalPos); 921e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.trim(); 922e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 923e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 924e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber val.trim(); 925e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 9263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("key=%s value=%s", key.c_str(), val.c_str()); 927e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 928e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.tolower(); 929e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 930e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (key == "method" || key == "uri" || key == "iv") { 931e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (meta->get() == NULL) { 932e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber *meta = new AMessage; 933e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 934e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 935decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber if (key == "uri") { 936decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber if (val.size() >= 2 937decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber && val.c_str()[0] == '"' 938decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber && val.c_str()[val.size() - 1] == '"') { 939decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber // Remove surrounding quotes. 940decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber AString tmp(val, 1, val.size() - 2); 941decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber val = tmp; 942decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } 943decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber 944decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber AString absURI; 945decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber if (MakeURL(baseURI.c_str(), val.c_str(), &absURI)) { 946decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber val = absURI; 947decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } else { 948a1df816c0677185534babba6ffc29970b048e52eLajos Molnar ALOGE("failed to make absolute url for %s.", 949a1df816c0677185534babba6ffc29970b048e52eLajos Molnar uriDebugString(baseURI).c_str()); 950decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } 951decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } 952decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber 953e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.insert(AString("cipher-"), 0); 954e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 955e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber (*meta)->setString(key.c_str(), val.c_str(), val.size()); 956e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 957e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 958e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 959e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return OK; 960e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber} 961e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 962e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber// static 9632aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huberstatus_t M3UParser::parseByteRange( 9642aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const AString &line, uint64_t curOffset, 9652aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber uint64_t *length, uint64_t *offset) { 9662aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber ssize_t colonPos = line.find(":"); 9672aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9682aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (colonPos < 0) { 9692aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 9702aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 9712aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9722aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber ssize_t atPos = line.find("@", colonPos + 1); 9732aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9742aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber AString lenStr; 9752aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (atPos < 0) { 9762aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber lenStr = AString(line, colonPos + 1, line.size() - colonPos - 1); 9772aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } else { 9782aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber lenStr = AString(line, colonPos + 1, atPos - colonPos - 1); 9792aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 9802aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9812aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber lenStr.trim(); 9822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const char *s = lenStr.c_str(); 9842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber char *end; 9852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber *length = strtoull(s, &end, 10); 9862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (s == end || *end != '\0') { 9882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 9892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 9902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (atPos >= 0) { 9922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber AString offStr = AString(line, atPos + 1, line.size() - atPos - 1); 9932aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber offStr.trim(); 9942aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const char *s = offStr.c_str(); 9962aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber *offset = strtoull(s, &end, 10); 9972aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9982aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (s == end || *end != '\0') { 9992aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 10002aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 10012aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } else { 10022aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber *offset = curOffset; 10032aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 10042aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 10052aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return OK; 10062aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber} 10072aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 100814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t M3UParser::parseMedia(const AString &line) { 100914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t colonPos = line.find(":"); 101014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 101114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (colonPos < 0) { 101214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 101314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 101414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 101514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupType = false; 101614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber MediaGroup::Type groupType = MediaGroup::TYPE_AUDIO; 101714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 101814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupID = false; 101914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupID; 102014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupLanguage = false; 102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupLanguage; 102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupName = false; 102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupName; 102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupAutoselect = false; 102814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool groupAutoselect = false; 102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupDefault = false; 103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool groupDefault = false; 103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupForced = false; 103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool groupForced = false; 103514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupURI = false; 103714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupURI; 103814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t offset = colonPos + 1; 104014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 104114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (offset < line.size()) { 104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t end = FindNextUnquoted(line, ',', offset); 104314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end < 0) { 104414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber end = line.size(); 104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString attr(line, offset, end - offset); 104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber attr.trim(); 104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber offset = end + 1; 105114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t equalPos = attr.find("="); 105314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (equalPos < 0) { 105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber continue; 105514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 105614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString key(attr, 0, equalPos); 105814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key.trim(); 105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 106014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.trim(); 106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 106314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("key=%s value=%s", key.c_str(), val.c_str()); 106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 106514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("type", key.c_str())) { 106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("subtitles", val.c_str())) { 106714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType = MediaGroup::TYPE_SUBS; 106814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("audio", val.c_str())) { 106914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType = MediaGroup::TYPE_AUDIO; 107014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("video", val.c_str())) { 107114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType = MediaGroup::TYPE_VIDEO; 107299cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang } else if (!strcasecmp("closed-captions", val.c_str())){ 107399cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang groupType = MediaGroup::TYPE_CC; 107414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 107514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Invalid media group type '%s'", val.c_str()); 107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 107814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 107914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupType = true; 108014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("group-id", key.c_str())) { 108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 108214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 108314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 108414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for GROUP-ID, got '%s' instead.", 108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 108614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupID.setTo(val, 1, val.size() - 2); 109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupID = true; 109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("language", key.c_str())) { 109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for LANGUAGE, got '%s' instead.", 109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupLanguage.setTo(val, 1, val.size() - 2); 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupLanguage = true; 110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("name", key.c_str())) { 110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for NAME, got '%s' instead.", 110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 111014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 111114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 111214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupName.setTo(val, 1, val.size() - 2); 111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupName = true; 111614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("autoselect", key.c_str())) { 111714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupAutoselect = false; 111814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("YES", val.c_str())) { 111914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupAutoselect = true; 112014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("NO", val.c_str())) { 112114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupAutoselect = false; 112214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 112314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected YES or NO for AUTOSELECT attribute, " 112414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 112514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 112614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 112914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 113014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupAutoselect = true; 113114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("default", key.c_str())) { 113214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupDefault = false; 113314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("YES", val.c_str())) { 113414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupDefault = true; 113514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("NO", val.c_str())) { 113614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupDefault = false; 113714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 113814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected YES or NO for DEFAULT attribute, " 113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 114014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 114114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 114314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 114414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupDefault = true; 114614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("forced", key.c_str())) { 114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupForced = false; 114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("YES", val.c_str())) { 114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupForced = true; 115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("NO", val.c_str())) { 115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupForced = false; 115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected YES or NO for FORCED attribute, " 115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 115614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupForced = true; 116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("uri", key.c_str())) { 116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for URI, got '%s' instead.", 116614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 116914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString tmp(val, 1, val.size() - 2); 117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!MakeURL(mBaseURI.c_str(), tmp.c_str(), &groupURI)) { 117414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("Failed to make absolute URI from '%s'.", tmp.c_str()); 117514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 117614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupURI = true; 117814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 117914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 118014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!haveGroupType || !haveGroupID || !haveGroupName) { 118214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Incomplete EXT-X-MEDIA element."); 118314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 118414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 118514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118699cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang if (groupType == MediaGroup::TYPE_CC) { 118799cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang // TODO: ignore this for now. 118899cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang // CC track will be detected by CCDecoder. But we still need to 118999cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang // pass the CC track flags (lang, auto) to the app in the future. 119099cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang return OK; 119199cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang } 119299cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang 119314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t flags = 0; 119414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupAutoselect && groupAutoselect) { 119514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_AUTOSELECT; 119614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 119714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupDefault && groupDefault) { 119814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_DEFAULT; 119914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 120014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupForced) { 120114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupType != MediaGroup::TYPE_SUBS) { 120214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("The FORCED attribute MUST not be present on anything " 120314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "but SUBS media."); 120414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 120514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 120614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 120714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 120814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupForced) { 120914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_FORCED; 121014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 121114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 121214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupLanguage) { 121314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_HAS_LANGUAGE; 121414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 121514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupURI) { 121614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_HAS_URI; 121714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 121814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 121914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t groupIndex = mMediaGroups.indexOfKey(groupID); 122014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MediaGroup> group; 122114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 122214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupIndex < 0) { 122314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber group = new MediaGroup(groupType); 122414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mMediaGroups.add(groupID, group); 122514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 122614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber group = mMediaGroups.valueAt(groupIndex); 122714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 122814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (group->type() != groupType) { 122914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Attempt to put media item under group of different type " 123014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "(groupType = %d, item type = %d", 123114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber group->type(), 123214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType); 123314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 123414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 123514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 123614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 123714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 123814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return group->addMedia( 123914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupName.c_str(), 124014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupURI ? groupURI.c_str() : NULL, 124114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupLanguage ? groupLanguage.c_str() : NULL, 124214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags); 124314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1244309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1245309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih// static 1246309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shihstatus_t M3UParser::parseDiscontinuitySequence(const AString &line, size_t *seq) { 1247309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih ssize_t colonPos = line.find(":"); 1248309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1249309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (colonPos < 0) { 1250309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return ERROR_MALFORMED; 1251309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1252309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1253309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t x; 1254309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih status_t err = ParseInt32(line.c_str() + colonPos + 1, &x); 1255309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (err != OK) { 1256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return err; 1257309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1258309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1259309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (x < 0) { 1260309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return ERROR_MALFORMED; 1261309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1262309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1263309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (seq) { 1264309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih *seq = x; 1265309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1266309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return OK; 1267309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih} 126814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 12692aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber// static 1270e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::ParseInt32(const char *s, int32_t *x) { 1271e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber char *end; 1272e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber long lval = strtol(s, &end, 10); 1273e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1274e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (end == s || (*end != '\0' && *end != ',')) { 1275e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 1276e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 1277e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1278e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *x = (int32_t)lval; 1279e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1280e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 1281e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 1282e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 12839067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber// static 12849067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huberstatus_t M3UParser::ParseDouble(const char *s, double *x) { 12859067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber char *end; 12869067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber double dval = strtod(s, &end); 12879067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 12889067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (end == s || (*end != '\0' && *end != ',')) { 12899067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return ERROR_MALFORMED; 12909067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 12919067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 12929067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber *x = dval; 12939067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 12949067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return OK; 12959067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber} 12969067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 1297ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih// static 1298ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shihbool M3UParser::isQuotedString(const AString &str) { 1299ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (str.size() < 2 1300ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih || str.c_str()[0] != '"' 1301ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih || str.c_str()[str.size() - 1] != '"') { 1302ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 1303ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1304ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return true; 1305ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih} 1306ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1307ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih// static 1308ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert ShihAString M3UParser::unquoteString(const AString &str) { 1309ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!isQuotedString(str)) { 1310ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return str; 1311ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1312ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return AString(str, 1, str.size() - 2); 1313ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih} 1314ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1315ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih// static 1316ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shihbool M3UParser::codecIsType(const AString &codec, const char *type) { 1317ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (codec.size() < 4) { 1318ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 1319ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1320ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih const char *c = codec.c_str(); 1321ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih switch (FOURCC(c[0], c[1], c[2], c[3])) { 1322ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // List extracted from http://www.mp4ra.org/codecs.html 1323ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ac-3': 1324ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'alac': 1325ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dra1': 1326ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtsc': 1327ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtse': 1328ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtsh': 1329ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtsl': 1330ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ec-3': 1331ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'enca': 1332ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'g719': 1333ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'g726': 1334ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'm4ae': 1335ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mlpa': 1336ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mp4a': 1337ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'raw ': 1338ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'samr': 1339ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sawb': 1340ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sawp': 1341ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sevc': 1342ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sqcp': 1343ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ssmv': 1344ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'twos': 1345ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'agsm': 1346ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'alaw': 1347ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvi ': 1348ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'fl32': 1349ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'fl64': 1350ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ima4': 1351ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'in24': 1352ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'in32': 1353ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'lpcm': 1354ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Qclp': 1355ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'QDM2': 1356ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'QDMC': 1357ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ulaw': 1358ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'vdva': 1359ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return !strcmp("audio", type); 1360ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1361ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'avc1': 1362ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'avc2': 1363ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'avcp': 1364ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'drac': 1365ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'encv': 1366ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mjp2': 1367ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mp4v': 1368ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mvc1': 1369ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mvc2': 1370ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'resv': 1371ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 's263': 1372ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'svc1': 1373ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'vc-1': 1374ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'CFHD': 1375ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'civd': 1376ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DV10': 1377ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvh5': 1378ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvh6': 1379ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvhp': 1380ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVOO': 1381ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVOR': 1382ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVTV': 1383ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVVT': 1384ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'flic': 1385ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'gif ': 1386ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'h261': 1387ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'h263': 1388ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'HD10': 1389ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'jpeg': 1390ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'M105': 1391ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mjpa': 1392ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mjpb': 1393ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'png ': 1394ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'PNTG': 1395ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'rle ': 1396ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'rpza': 1397ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr0': 1398ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr1': 1399ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr2': 1400ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr3': 1401ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr4': 1402ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'SVQ1': 1403ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'SVQ3': 1404ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'tga ': 1405ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'tiff': 1406ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'WRLE': 1407ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return !strcmp("video", type); 1408ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1409ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih default: 1410ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 1411ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1412ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih} 1413ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1414e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} // namespace android 1415