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"); 606985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih } else if (line.startsWith("#EXT-X-DISCONTINUITY-SEQUENCE")) { 607985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih if (mIsVariantPlaylist) { 608985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih return ERROR_MALFORMED; 609985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih } 610985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih size_t seq; 611985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih err = parseDiscontinuitySequence(line, &seq); 612985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih if (err == OK) { 613985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih mDiscontinuitySeq = seq; 614985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih ALOGI("mDiscontinuitySeq %zu", mDiscontinuitySeq); 615985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih } else { 616985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih ALOGI("Failed to parseDiscontinuitySequence %d", err); 617985746d11c888e110d5ea34d815efeb1115de0c6Robert Shih } 6182a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } else if (line.startsWith("#EXT-X-DISCONTINUITY")) { 6192a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (mIsVariantPlaylist) { 6202a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return ERROR_MALFORMED; 6212a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 6222a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (itemMeta == NULL) { 6232a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber itemMeta = new AMessage; 6242a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 6252a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber itemMeta->setInt32("discontinuity", true); 626c4547ba77f78632172db3647a09659d9863d3b5cChong Zhang ++mDiscontinuityCount; 627e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXT-X-STREAM-INF")) { 628e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mMeta != NULL) { 629e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 630e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 631e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsVariantPlaylist = true; 6322a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber err = parseStreamInf(line, &itemMeta); 6332aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } else if (line.startsWith("#EXT-X-BYTERANGE")) { 6342aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (mIsVariantPlaylist) { 6352aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 6362aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 6372aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6382aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber uint64_t length, offset; 6392aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber err = parseByteRange(line, segmentRangeOffset, &length, &offset); 6402aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6412aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (err == OK) { 6422aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (itemMeta == NULL) { 6432aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber itemMeta = new AMessage; 6442aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 6452aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6462aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber itemMeta->setInt64("range-offset", offset); 6472aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber itemMeta->setInt64("range-length", length); 6482aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 6492aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber segmentRangeOffset = offset + length; 6502aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 65114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (line.startsWith("#EXT-X-MEDIA")) { 65214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber err = parseMedia(line); 653e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 654e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 655e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (err != OK) { 656e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return err; 657e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 658e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 659e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 660e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!line.startsWith("#")) { 661e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!mIsVariantPlaylist) { 6629067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber int64_t durationUs; 663e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (itemMeta == NULL 6649067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber || !itemMeta->findInt64("durationUs", &durationUs)) { 665e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 666e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 667d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang itemMeta->setInt32("discontinuity-sequence", 668d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang mDiscontinuitySeq + mDiscontinuityCount); 669e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 670e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 671e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mItems.push(); 672e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber Item *item = &mItems.editItemAt(mItems.size() - 1); 673e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 674e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber CHECK(MakeURL(mBaseURI.c_str(), line.c_str(), &item->mURI)); 675e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 676e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber item->mMeta = itemMeta; 677e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 678e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber itemMeta.clear(); 679e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 680e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 681e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber offset = offsetLF + 1; 682e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ++lineNo; 683e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 684e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 685d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang // error checking of all fields that's required to appear once 686978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // (currently only checking "target-duration"), and 687978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang // initialization of playlist properties (eg. mTargetDurationUs) 688978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (!mIsVariantPlaylist) { 689978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang int32_t targetDurationSecs; 690978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mMeta == NULL || !mMeta->findInt32( 691978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang "target-duration", &targetDurationSecs)) { 692978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang ALOGE("Media playlist missing #EXT-X-TARGETDURATION"); 693978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang return ERROR_MALFORMED; 694978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 695978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mTargetDurationUs = targetDurationSecs * 1000000ll; 696978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang 697978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mFirstSeqNumber = 0; 698978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang if (mMeta != NULL) { 699978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mMeta->findInt32("media-sequence", &mFirstSeqNumber); 700978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang } 701978449984366946a2e5c9f7cf350746f4306caf8Chong Zhang mLastSeqNumber = mFirstSeqNumber + mItems.size() - 1; 702d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang } 703d47dfcb5a2e5901c96fc92662cec7aa30f7f8843Chong Zhang 704af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih for (size_t i = 0; i < mItems.size(); ++i) { 705af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih sp<AMessage> meta = mItems.itemAt(i).mMeta; 706af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih const char *keys[] = {"audio", "video", "subtitles"}; 707af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih for (size_t j = 0; j < sizeof(keys) / sizeof(const char *); ++j) { 708af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih AString groupID; 709af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih if (meta->findString(keys[j], &groupID)) { 710af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih ssize_t groupIndex = mMediaGroups.indexOfKey(groupID); 711af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih if (groupIndex < 0) { 712af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih ALOGE("Undefined media group '%s' referenced in stream info.", 713af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih groupID.c_str()); 714af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih return ERROR_MALFORMED; 715af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih } 716af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih } 717af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih } 718af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih } 719af464030d7f0a1d97eb308a06a873b7320f86aa9Robert Shih 720e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 721e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 722e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 723e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber// static 724e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::parseMetaData( 725e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const AString &line, sp<AMessage> *meta, const char *key) { 726e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ssize_t colonPos = line.find(":"); 727e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 728e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (colonPos < 0) { 729e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 730e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 731e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 732e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber int32_t x; 733e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber status_t err = ParseInt32(line.c_str() + colonPos + 1, &x); 734e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 735e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (err != OK) { 736e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return err; 737e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 738e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 739e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (meta->get() == NULL) { 740e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *meta = new AMessage; 741e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 742e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber (*meta)->setInt32(key, x); 743e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 744e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 745e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 746e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 747e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber// static 7489067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huberstatus_t M3UParser::parseMetaDataDuration( 7499067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber const AString &line, sp<AMessage> *meta, const char *key) { 7509067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber ssize_t colonPos = line.find(":"); 7519067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7529067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (colonPos < 0) { 7539067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return ERROR_MALFORMED; 7549067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 7559067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7569067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber double x; 7579067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber status_t err = ParseDouble(line.c_str() + colonPos + 1, &x); 7589067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7599067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (err != OK) { 7609067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return err; 7619067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 7629067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7639067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (meta->get() == NULL) { 7649067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber *meta = new AMessage; 7659067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 766abd5feeea499ee7337125223df4ea22cae19cd20Oscar Rydhé (*meta)->setInt64(key, (int64_t)(x * 1E6)); 7679067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 7689067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return OK; 7699067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber} 7709067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 77114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// Find the next occurence of the character "what" at or after "offset", 77214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// but ignore occurences between quotation marks. 77314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber// Return the index of the occurrence or -1 if not found. 77414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatic ssize_t FindNextUnquoted( 77514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &line, char what, size_t offset) { 77614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber CHECK_NE((int)what, (int)'"'); 77714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 77814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool quoted = false; 77914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (offset < line.size()) { 78014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber char c = line.c_str()[offset]; 78114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (c == '"') { 78314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber quoted = !quoted; 78414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (c == what && !quoted) { 78514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return offset; 78614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 78714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 78814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ++offset; 78914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 79014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 79114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return -1; 79214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 79314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 7942a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huberstatus_t M3UParser::parseStreamInf( 79514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber const AString &line, sp<AMessage> *meta) const { 7962a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t colonPos = line.find(":"); 7972a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 7982a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (colonPos < 0) { 7992a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return ERROR_MALFORMED; 8002a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8012a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8022a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber size_t offset = colonPos + 1; 8032a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8042a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber while (offset < line.size()) { 80514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t end = FindNextUnquoted(line, ',', offset); 8062a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (end < 0) { 8072a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber end = line.size(); 8082a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8092a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8102a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString attr(line, offset, end - offset); 8112a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber attr.trim(); 8122a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8132a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber offset = end + 1; 8142a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8152a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t equalPos = attr.find("="); 8162a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (equalPos < 0) { 8172a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 8182a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8192a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8202a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString key(attr, 0, equalPos); 8212a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber key.trim(); 8222a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8232a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 8242a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber val.trim(); 8252a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("key=%s value=%s", key.c_str(), val.c_str()); 8272a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8282a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (!strcasecmp("bandwidth", key.c_str())) { 8292a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const char *s = val.c_str(); 8302a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber char *end; 8312a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber unsigned long x = strtoul(s, &end, 10); 8322a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8332a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (end == s || *end != '\0') { 8342a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber // malformed 8352a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 8362a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8372a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8382a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (meta->get() == NULL) { 8392a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber *meta = new AMessage; 8402a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8412a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber (*meta)->setInt32("bandwidth", x); 842ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } else if (!strcasecmp("codecs", key.c_str())) { 843ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!isQuotedString(val)) { 844ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih ALOGE("Expected quoted string for %s attribute, " 845ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih "got '%s' instead.", 846ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih key.c_str(), val.c_str());; 847ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 848ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return ERROR_MALFORMED; 849ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 850ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 851ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih key.tolower(); 852ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih const AString &codecs = unquoteString(val); 8535154f98277922aba7103ac19529ecc00b1889c1eRobert Shih if (meta->get() == NULL) { 8545154f98277922aba7103ac19529ecc00b1889c1eRobert Shih *meta = new AMessage; 8555154f98277922aba7103ac19529ecc00b1889c1eRobert Shih } 856ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih (*meta)->setString(key.c_str(), codecs.c_str()); 857a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } else if (!strcasecmp("resolution", key.c_str())) { 858a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang const char *s = val.c_str(); 859a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang char *end; 860a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang unsigned long width = strtoul(s, &end, 10); 861a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 862a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (end == s || *end != 'x') { 863a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang // malformed 864a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang continue; 865a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 866a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 867a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang s = end + 1; 868a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang unsigned long height = strtoul(s, &end, 10); 869a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 870a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (end == s || *end != '\0') { 871a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang // malformed 872a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang continue; 873a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 874a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang 875a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang if (meta->get() == NULL) { 876a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang *meta = new AMessage; 877a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang } 878a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang (*meta)->setInt32("width", width); 879a0d0ba51ad60a68117a0ee78e37ab78715b8a069Chong Zhang (*meta)->setInt32("height", height); 88014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("audio", key.c_str()) 88114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || !strcasecmp("video", key.c_str()) 88214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || !strcasecmp("subtitles", key.c_str())) { 883ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!isQuotedString(val)) { 88414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for %s attribute, " 88514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 88614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key.c_str(), val.c_str()); 88714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 88814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 88914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 8902a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 891ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih const AString &groupID = unquoteString(val); 89214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key.tolower(); 8935154f98277922aba7103ac19529ecc00b1889c1eRobert Shih if (meta->get() == NULL) { 8945154f98277922aba7103ac19529ecc00b1889c1eRobert Shih *meta = new AMessage; 8955154f98277922aba7103ac19529ecc00b1889c1eRobert Shih } 89614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber (*meta)->setString(key.c_str(), groupID.c_str()); 8970a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber } 8980a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber } 8990a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber 90014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return OK; 9010a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber} 9020a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber 9032a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber// static 904e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huberstatus_t M3UParser::parseCipherInfo( 905decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber const AString &line, sp<AMessage> *meta, const AString &baseURI) { 906e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t colonPos = line.find(":"); 907e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 908e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (colonPos < 0) { 909e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return ERROR_MALFORMED; 910e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 911e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 912e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber size_t offset = colonPos + 1; 913e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 914e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber while (offset < line.size()) { 9150a73d81f213fb2d6f2fdd59c4dda047bf453bb1cAndreas Huber ssize_t end = FindNextUnquoted(line, ',', offset); 916e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (end < 0) { 917e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber end = line.size(); 918e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 919e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 920e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString attr(line, offset, end - offset); 921e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber attr.trim(); 922e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 923e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber offset = end + 1; 924e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 925e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t equalPos = attr.find("="); 926e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (equalPos < 0) { 927e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber continue; 928e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 929e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 930e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString key(attr, 0, equalPos); 931e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.trim(); 932e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 933e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 934e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber val.trim(); 935e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 9363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("key=%s value=%s", key.c_str(), val.c_str()); 937e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 938e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.tolower(); 939e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 940e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (key == "method" || key == "uri" || key == "iv") { 941e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (meta->get() == NULL) { 942e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber *meta = new AMessage; 943e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 944e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 945decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber if (key == "uri") { 946decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber if (val.size() >= 2 947decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber && val.c_str()[0] == '"' 948decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber && val.c_str()[val.size() - 1] == '"') { 949decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber // Remove surrounding quotes. 950decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber AString tmp(val, 1, val.size() - 2); 951decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber val = tmp; 952decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } 953decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber 954decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber AString absURI; 955decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber if (MakeURL(baseURI.c_str(), val.c_str(), &absURI)) { 956decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber val = absURI; 957decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } else { 958a1df816c0677185534babba6ffc29970b048e52eLajos Molnar ALOGE("failed to make absolute url for %s.", 959a1df816c0677185534babba6ffc29970b048e52eLajos Molnar uriDebugString(baseURI).c_str()); 960decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } 961decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber } 962decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber 963e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.insert(AString("cipher-"), 0); 964e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 965e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber (*meta)->setString(key.c_str(), val.c_str(), val.size()); 966e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 967e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 968e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 969e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return OK; 970e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber} 971e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 972e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber// static 9732aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huberstatus_t M3UParser::parseByteRange( 9742aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const AString &line, uint64_t curOffset, 9752aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber uint64_t *length, uint64_t *offset) { 9762aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber ssize_t colonPos = line.find(":"); 9772aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9782aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (colonPos < 0) { 9792aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 9802aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 9812aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber ssize_t atPos = line.find("@", colonPos + 1); 9832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber AString lenStr; 9852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (atPos < 0) { 9862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber lenStr = AString(line, colonPos + 1, line.size() - colonPos - 1); 9872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } else { 9882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber lenStr = AString(line, colonPos + 1, atPos - colonPos - 1); 9892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 9902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber lenStr.trim(); 9922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9932aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const char *s = lenStr.c_str(); 9942aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber char *end; 9952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber *length = strtoull(s, &end, 10); 9962aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 9972aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (s == end || *end != '\0') { 9982aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 9992aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 10002aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 10012aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (atPos >= 0) { 10022aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber AString offStr = AString(line, atPos + 1, line.size() - atPos - 1); 10032aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber offStr.trim(); 10042aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 10052aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber const char *s = offStr.c_str(); 10062aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber *offset = strtoull(s, &end, 10); 10072aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 10082aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber if (s == end || *end != '\0') { 10092aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return ERROR_MALFORMED; 10102aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 10112aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } else { 10122aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber *offset = curOffset; 10132aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber } 10142aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 10152aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber return OK; 10162aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber} 10172aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber 101814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberstatus_t M3UParser::parseMedia(const AString &line) { 101914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t colonPos = line.find(":"); 102014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (colonPos < 0) { 102214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 102314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 102414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupType = false; 102614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber MediaGroup::Type groupType = MediaGroup::TYPE_AUDIO; 102714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 102814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupID = false; 102914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupID; 103014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupLanguage = false; 103214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupLanguage; 103314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupName = false; 103514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupName; 103614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 103714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupAutoselect = false; 103814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool groupAutoselect = false; 103914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 104014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupDefault = false; 104114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool groupDefault = false; 104214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 104314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupForced = false; 104414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool groupForced = false; 104514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 104614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber bool haveGroupURI = false; 104714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString groupURI; 104814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 104914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber size_t offset = colonPos + 1; 105014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 105114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber while (offset < line.size()) { 105214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t end = FindNextUnquoted(line, ',', offset); 105314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (end < 0) { 105414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber end = line.size(); 105514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 105614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 105714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString attr(line, offset, end - offset); 105814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber attr.trim(); 105914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 106014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber offset = end + 1; 106114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 106214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t equalPos = attr.find("="); 106314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (equalPos < 0) { 106414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber continue; 106514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 106614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 106714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString key(attr, 0, equalPos); 106814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber key.trim(); 106914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 107014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 107114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.trim(); 107214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 107314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGV("key=%s value=%s", key.c_str(), val.c_str()); 107414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 107514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("type", key.c_str())) { 107614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("subtitles", val.c_str())) { 107714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType = MediaGroup::TYPE_SUBS; 107814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("audio", val.c_str())) { 107914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType = MediaGroup::TYPE_AUDIO; 108014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("video", val.c_str())) { 108114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType = MediaGroup::TYPE_VIDEO; 108299cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang } else if (!strcasecmp("closed-captions", val.c_str())){ 108399cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang groupType = MediaGroup::TYPE_CC; 108414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 108514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Invalid media group type '%s'", val.c_str()); 108614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 108714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 108814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 108914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupType = true; 109014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("group-id", key.c_str())) { 109114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 109214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 109314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 109414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for GROUP-ID, got '%s' instead.", 109514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 109614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 109714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 109814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 109914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 110014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupID.setTo(val, 1, val.size() - 2); 110114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupID = true; 110214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("language", key.c_str())) { 110314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 110414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 110514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 110614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for LANGUAGE, got '%s' instead.", 110714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 110814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 110914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 111014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 111114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 111214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupLanguage.setTo(val, 1, val.size() - 2); 111314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupLanguage = true; 111414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("name", key.c_str())) { 111514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 111614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 111714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 111814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for NAME, got '%s' instead.", 111914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 112014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 112114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 112214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 112314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 112414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupName.setTo(val, 1, val.size() - 2); 112514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupName = true; 112614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("autoselect", key.c_str())) { 112714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupAutoselect = false; 112814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("YES", val.c_str())) { 112914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupAutoselect = true; 113014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("NO", val.c_str())) { 113114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupAutoselect = false; 113214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 113314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected YES or NO for AUTOSELECT attribute, " 113414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 113514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 113614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 113714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 113814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 113914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 114014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupAutoselect = true; 114114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("default", key.c_str())) { 114214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupDefault = false; 114314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("YES", val.c_str())) { 114414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupDefault = true; 114514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("NO", val.c_str())) { 114614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupDefault = false; 114714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 114814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected YES or NO for DEFAULT attribute, " 114914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 115014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 115114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 115314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 115414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 115514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupDefault = true; 115614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("forced", key.c_str())) { 115714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupForced = false; 115814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!strcasecmp("YES", val.c_str())) { 115914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupForced = true; 116014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("NO", val.c_str())) { 116114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupForced = false; 116214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 116314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected YES or NO for FORCED attribute, " 116414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "got '%s' instead.", 116514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 116614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 116714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 116814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 116914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupForced = true; 117114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else if (!strcasecmp("uri", key.c_str())) { 117214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (val.size() < 2 117314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[0] != '"' 117414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber || val.c_str()[val.size() - 1] != '"') { 117514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Expected quoted string for URI, got '%s' instead.", 117614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber val.c_str()); 117714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 117814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 117914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 118014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber AString tmp(val, 1, val.size() - 2); 118214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!MakeURL(mBaseURI.c_str(), tmp.c_str(), &groupURI)) { 118414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGI("Failed to make absolute URI from '%s'.", tmp.c_str()); 118514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 118614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 118714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupURI = true; 118814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 118914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 119014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 119114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (!haveGroupType || !haveGroupID || !haveGroupName) { 119214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Incomplete EXT-X-MEDIA element."); 119314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 119414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 119514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 119699cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang if (groupType == MediaGroup::TYPE_CC) { 119799cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang // TODO: ignore this for now. 119899cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang // CC track will be detected by CCDecoder. But we still need to 119999cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang // pass the CC track flags (lang, auto) to the app in the future. 120099cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang return OK; 120199cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang } 120299cef1ef1cf1232966fabf3793ce7964c01474d7Chong Zhang 120314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber uint32_t flags = 0; 120414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupAutoselect && groupAutoselect) { 120514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_AUTOSELECT; 120614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 120714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupDefault && groupDefault) { 120814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_DEFAULT; 120914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 121014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupForced) { 121114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupType != MediaGroup::TYPE_SUBS) { 121214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("The FORCED attribute MUST not be present on anything " 121314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "but SUBS media."); 121414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 121514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 121614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 121714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 121814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupForced) { 121914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_FORCED; 122014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 122114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 122214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupLanguage) { 122314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_HAS_LANGUAGE; 122414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 122514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (haveGroupURI) { 122614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags |= MediaGroup::FLAG_HAS_URI; 122714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 122814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 122914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ssize_t groupIndex = mMediaGroups.indexOfKey(groupID); 123014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber sp<MediaGroup> group; 123114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 123214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (groupIndex < 0) { 123314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber group = new MediaGroup(groupType); 123414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber mMediaGroups.add(groupID, group); 123514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } else { 123614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber group = mMediaGroups.valueAt(groupIndex); 123714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 123814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber if (group->type() != groupType) { 123914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber ALOGE("Attempt to put media item under group of different type " 124014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber "(groupType = %d, item type = %d", 124114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber group->type(), 124214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupType); 124314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 124414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return ERROR_MALFORMED; 124514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 124614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber } 124714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 124814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return group->addMedia( 124914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber groupName.c_str(), 125014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupURI ? groupURI.c_str() : NULL, 125114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber haveGroupLanguage ? groupLanguage.c_str() : NULL, 125214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber flags); 125314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber} 1254309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1255309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih// static 1256309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shihstatus_t M3UParser::parseDiscontinuitySequence(const AString &line, size_t *seq) { 1257309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih ssize_t colonPos = line.find(":"); 1258309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1259309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (colonPos < 0) { 1260309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return ERROR_MALFORMED; 1261309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1262309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1263309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih int32_t x; 1264309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih status_t err = ParseInt32(line.c_str() + colonPos + 1, &x); 1265309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (err != OK) { 1266309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return err; 1267309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1268309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1269309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (x < 0) { 1270309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return ERROR_MALFORMED; 1271309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1272309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih 1273309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih if (seq) { 1274309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih *seq = x; 1275309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih } 1276309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih return OK; 1277309aa8bf5e4cd66fe988adf2654cac3fadc2a1c3Robert Shih} 127814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber 12792aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber// static 1280e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::ParseInt32(const char *s, int32_t *x) { 1281e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber char *end; 1282e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber long lval = strtol(s, &end, 10); 1283e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1284e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (end == s || (*end != '\0' && *end != ',')) { 1285e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 1286e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 1287e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1288e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *x = (int32_t)lval; 1289e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1290e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 1291e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 1292e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 12939067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber// static 12949067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huberstatus_t M3UParser::ParseDouble(const char *s, double *x) { 12959067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber char *end; 12969067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber double dval = strtod(s, &end); 12979067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 12989067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber if (end == s || (*end != '\0' && *end != ',')) { 12999067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return ERROR_MALFORMED; 13009067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber } 13019067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 13029067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber *x = dval; 13039067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 13049067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber return OK; 13059067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber} 13069067e30b3ccb3a07e41b61af22c036378053a9a3Andreas Huber 1307ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih// static 1308ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shihbool M3UParser::isQuotedString(const AString &str) { 1309ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (str.size() < 2 1310ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih || str.c_str()[0] != '"' 1311ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih || str.c_str()[str.size() - 1] != '"') { 1312ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 1313ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1314ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return true; 1315ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih} 1316ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1317ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih// static 1318ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert ShihAString M3UParser::unquoteString(const AString &str) { 1319ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (!isQuotedString(str)) { 1320ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return str; 1321ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1322ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return AString(str, 1, str.size() - 2); 1323ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih} 1324ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1325ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih// static 1326ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shihbool M3UParser::codecIsType(const AString &codec, const char *type) { 1327ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih if (codec.size() < 4) { 1328ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 1329ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1330ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih const char *c = codec.c_str(); 1331ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih switch (FOURCC(c[0], c[1], c[2], c[3])) { 1332ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih // List extracted from http://www.mp4ra.org/codecs.html 1333ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ac-3': 1334ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'alac': 1335ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dra1': 1336ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtsc': 1337ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtse': 1338ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtsh': 1339ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dtsl': 1340ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ec-3': 1341ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'enca': 1342ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'g719': 1343ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'g726': 1344ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'm4ae': 1345ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mlpa': 1346ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mp4a': 1347ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'raw ': 1348ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'samr': 1349ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sawb': 1350ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sawp': 1351ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sevc': 1352ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'sqcp': 1353ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ssmv': 1354ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'twos': 1355ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'agsm': 1356ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'alaw': 1357ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvi ': 1358ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'fl32': 1359ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'fl64': 1360ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ima4': 1361ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'in24': 1362ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'in32': 1363ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'lpcm': 1364ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Qclp': 1365ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'QDM2': 1366ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'QDMC': 1367ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'ulaw': 1368ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'vdva': 1369ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return !strcmp("audio", type); 1370ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1371ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'avc1': 1372ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'avc2': 1373ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'avcp': 1374ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'drac': 1375ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'encv': 1376ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mjp2': 1377ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mp4v': 1378ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mvc1': 1379ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mvc2': 1380ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'resv': 1381ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 's263': 1382ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'svc1': 1383ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'vc-1': 1384ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'CFHD': 1385ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'civd': 1386ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DV10': 1387ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvh5': 1388ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvh6': 1389ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'dvhp': 1390ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVOO': 1391ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVOR': 1392ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVTV': 1393ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'DVVT': 1394ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'flic': 1395ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'gif ': 1396ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'h261': 1397ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'h263': 1398ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'HD10': 1399ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'jpeg': 1400ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'M105': 1401ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mjpa': 1402ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'mjpb': 1403ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'png ': 1404ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'PNTG': 1405ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'rle ': 1406ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'rpza': 1407ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr0': 1408ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr1': 1409ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr2': 1410ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr3': 1411ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'Shr4': 1412ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'SVQ1': 1413ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'SVQ3': 1414ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'tga ': 1415ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'tiff': 1416ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih case 'WRLE': 1417ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return !strcmp("video", type); 1418ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1419ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih default: 1420ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih return false; 1421ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih } 1422ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih} 1423ef8adf8ce4ece039a839f42a22b436d8ae077f37Robert Shih 1424e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} // namespace android 1425