M3UParser.cpp revision e332a9181cf6a3155ed1a0fd2afc212ccb1f2753
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 17e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber#include "include/M3UParser.h" 18e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 19e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber#include <media/stagefright/foundation/AMessage.h> 20e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber#include <media/stagefright/MediaDebug.h> 21e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber#include <media/stagefright/MediaErrors.h> 22e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 23e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Hubernamespace android { 24e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 25e71d10e7ad55ccbcb0756c007caef1c959090384Andreas HuberM3UParser::M3UParser( 26e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const char *baseURI, const void *data, size_t size) 27e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber : mInitCheck(NO_INIT), 28e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mBaseURI(baseURI), 29e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsExtM3U(false), 30bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mIsVariantPlaylist(false), 31bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mIsComplete(false) { 32e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mInitCheck = parse(data, size); 33e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 34e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 35e71d10e7ad55ccbcb0756c007caef1c959090384Andreas HuberM3UParser::~M3UParser() { 36e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 37e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 38e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::initCheck() const { 39e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mInitCheck; 40e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 41e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 42e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberbool M3UParser::isExtM3U() const { 43e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mIsExtM3U; 44e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 45e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 46e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberbool M3UParser::isVariantPlaylist() const { 47e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mIsVariantPlaylist; 48e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 49e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 50bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huberbool M3UParser::isComplete() const { 51bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber return mIsComplete; 52bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber} 53bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 54e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Hubersp<AMessage> M3UParser::meta() { 55e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mMeta; 56e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 57e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 58e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Hubersize_t M3UParser::size() { 59e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return mItems.size(); 60e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 61e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 62e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberbool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) { 63e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber uri->clear(); 64e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (meta) { *meta = NULL; } 65e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 66e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (index >= mItems.size()) { 67e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return false; 68e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 69e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 70e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *uri = mItems.itemAt(index).mURI; 71e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 72e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (meta) { 73e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *meta = mItems.itemAt(index).mMeta; 74e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 75e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 76e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return true; 77e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 78e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 79e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatic bool MakeURL(const char *baseURL, const char *url, AString *out) { 80e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->clear(); 81e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 822a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (strncasecmp("http://", baseURL, 7) 832a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber && strncasecmp("file://", baseURL, 7)) { 84e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber // Base URL must be absolute 85e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return false; 86e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 87e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 88e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!strncasecmp("http://", url, 7)) { 89e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber // "url" is already an absolute URL, ignore base URL. 90e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->setTo(url); 91e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return true; 92e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 93e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 94e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber size_t n = strlen(baseURL); 95e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (baseURL[n - 1] == '/') { 96e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->setTo(baseURL); 97e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->append(url); 98e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else { 994e2ffa400b82559cab2c5717c8dcdff393d334a9Mike Lockwood const char *slashPos = strrchr(baseURL, '/'); 100e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 101e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (slashPos > &baseURL[6]) { 102e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->setTo(baseURL, slashPos - baseURL); 103e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else { 104e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->setTo(baseURL); 105e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 106e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 107e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->append("/"); 108e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber out->append(url); 109e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 110e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 111e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return true; 112e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 113e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 114e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::parse(const void *_data, size_t size) { 115e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber int32_t lineNo = 0; 116e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 117e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber sp<AMessage> itemMeta; 118e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 119e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const char *data = (const char *)_data; 120e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber size_t offset = 0; 121e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber while (offset < size) { 122e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber size_t offsetLF = offset; 123e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber while (offsetLF < size && data[offsetLF] != '\n') { 124e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ++offsetLF; 125e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 126e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (offsetLF >= size) { 127e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber break; 128e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 129e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 130e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber AString line; 131e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (offsetLF > offset && data[offsetLF - 1] == '\r') { 132e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber line.setTo(&data[offset], offsetLF - offset - 1); 133e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else { 134e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber line.setTo(&data[offset], offsetLF - offset); 135e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 136e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 1372a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber // LOGI("#%s#", line.c_str()); 1382a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 1392a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (line.empty()) { 1402a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber offset = offsetLF + 1; 1412a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 1422a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 143e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 144e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (lineNo == 0 && line == "#EXTM3U") { 145e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsExtM3U = true; 146e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 147e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 148e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsExtM3U) { 149e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber status_t err = OK; 150e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 151e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (line.startsWith("#EXT-X-TARGETDURATION")) { 152e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsVariantPlaylist) { 153e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 154e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 155e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber err = parseMetaData(line, &mMeta, "target-duration"); 156e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXT-X-MEDIA-SEQUENCE")) { 157e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsVariantPlaylist) { 158e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 159e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 160e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber err = parseMetaData(line, &mMeta, "media-sequence"); 161e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } else if (line.startsWith("#EXT-X-KEY")) { 162e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (mIsVariantPlaylist) { 163e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return ERROR_MALFORMED; 164e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 165e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber err = parseCipherInfo(line, &itemMeta); 166bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber } else if (line.startsWith("#EXT-X-ENDLIST")) { 167bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mIsComplete = true; 168e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXTINF")) { 169e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mIsVariantPlaylist) { 170e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 171e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 172e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber err = parseMetaData(line, &itemMeta, "duration"); 1732a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } else if (line.startsWith("#EXT-X-DISCONTINUITY")) { 1742a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (mIsVariantPlaylist) { 1752a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return ERROR_MALFORMED; 1762a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 1772a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (itemMeta == NULL) { 1782a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber itemMeta = new AMessage; 1792a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 1802a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber itemMeta->setInt32("discontinuity", true); 181e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } else if (line.startsWith("#EXT-X-STREAM-INF")) { 182e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (mMeta != NULL) { 183e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 184e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 185e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mIsVariantPlaylist = true; 1862a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber err = parseStreamInf(line, &itemMeta); 187e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 188e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 189e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (err != OK) { 190e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return err; 191e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 192e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 193e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 194e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!line.startsWith("#")) { 195e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (!mIsVariantPlaylist) { 196e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber int32_t durationSecs; 197e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (itemMeta == NULL 198e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber || !itemMeta->findInt32("duration", &durationSecs)) { 199e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 200e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 201e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 202e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 203e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber mItems.push(); 204e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber Item *item = &mItems.editItemAt(mItems.size() - 1); 205e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 206e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber CHECK(MakeURL(mBaseURI.c_str(), line.c_str(), &item->mURI)); 207e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 208e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber item->mMeta = itemMeta; 209e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 210e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber itemMeta.clear(); 211e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 212e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 213e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber offset = offsetLF + 1; 214e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ++lineNo; 215e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 216e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 217e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 218e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 219e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 220e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber// static 221e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::parseMetaData( 222e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber const AString &line, sp<AMessage> *meta, const char *key) { 223e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber ssize_t colonPos = line.find(":"); 224e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 225e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (colonPos < 0) { 226e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 227e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 228e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 229e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber int32_t x; 230e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber status_t err = ParseInt32(line.c_str() + colonPos + 1, &x); 231e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 232e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (err != OK) { 233e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return err; 234e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 235e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 236e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (meta->get() == NULL) { 237e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *meta = new AMessage; 238e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 239e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber (*meta)->setInt32(key, x); 240e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 241e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 242e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 243e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 244e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber// static 2452a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huberstatus_t M3UParser::parseStreamInf( 2462a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const AString &line, sp<AMessage> *meta) { 2472a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t colonPos = line.find(":"); 2482a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2492a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (colonPos < 0) { 2502a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return ERROR_MALFORMED; 2512a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2522a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2532a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber size_t offset = colonPos + 1; 2542a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2552a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber while (offset < line.size()) { 2562a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t end = line.find(",", offset); 2572a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (end < 0) { 2582a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber end = line.size(); 2592a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2602a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2612a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString attr(line, offset, end - offset); 2622a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber attr.trim(); 2632a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2642a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber offset = end + 1; 2652a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2662a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber ssize_t equalPos = attr.find("="); 2672a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (equalPos < 0) { 2682a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 2692a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2702a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2712a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString key(attr, 0, equalPos); 2722a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber key.trim(); 2732a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2742a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 2752a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber val.trim(); 2762a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2772a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber LOGV("key=%s value=%s", key.c_str(), val.c_str()); 2782a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2792a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (!strcasecmp("bandwidth", key.c_str())) { 2802a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const char *s = val.c_str(); 2812a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber char *end; 2822a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber unsigned long x = strtoul(s, &end, 10); 2832a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2842a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (end == s || *end != '\0') { 2852a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber // malformed 2862a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber continue; 2872a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2882a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2892a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (meta->get() == NULL) { 2902a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber *meta = new AMessage; 2912a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2922a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber (*meta)->setInt32("bandwidth", x); 2932a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2942a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 2952a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2962a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return OK; 2972a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber} 2982a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 2992a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber// static 300e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huberstatus_t M3UParser::parseCipherInfo( 301e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber const AString &line, sp<AMessage> *meta) { 302e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t colonPos = line.find(":"); 303e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 304e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (colonPos < 0) { 305e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return ERROR_MALFORMED; 306e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 307e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 308e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber size_t offset = colonPos + 1; 309e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 310e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber while (offset < line.size()) { 311e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t end = line.find(",", offset); 312e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (end < 0) { 313e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber end = line.size(); 314e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 315e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 316e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString attr(line, offset, end - offset); 317e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber attr.trim(); 318e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 319e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber offset = end + 1; 320e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 321e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber ssize_t equalPos = attr.find("="); 322e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (equalPos < 0) { 323e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber continue; 324e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 325e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 326e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString key(attr, 0, equalPos); 327e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.trim(); 328e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 329e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber AString val(attr, equalPos + 1, attr.size() - equalPos - 1); 330e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber val.trim(); 331e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 332e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber LOGV("key=%s value=%s", key.c_str(), val.c_str()); 333e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 334e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.tolower(); 335e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 336e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (key == "method" || key == "uri" || key == "iv") { 337e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (meta->get() == NULL) { 338e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber *meta = new AMessage; 339e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 340e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 341e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber key.insert(AString("cipher-"), 0); 342e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 343e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber (*meta)->setString(key.c_str(), val.c_str(), val.size()); 344e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 345e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 346e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 347e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return OK; 348e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber} 349e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 350e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber// static 351e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huberstatus_t M3UParser::ParseInt32(const char *s, int32_t *x) { 352e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber char *end; 353e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber long lval = strtol(s, &end, 10); 354e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 355e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber if (end == s || (*end != '\0' && *end != ',')) { 356e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return ERROR_MALFORMED; 357e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber } 358e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 359e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber *x = (int32_t)lval; 360e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 361e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber return OK; 362e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} 363e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber 364e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber} // namespace android 365