Merge "Add onExpirationUpdate and onKeyStatusChange listeners."
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index c908323..ac3be25 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1290,16 +1290,21 @@
}
default:
ALOGE("Unknown error from camera device: %d", errorCode);
- // no break
+ [[fallthrough]];
case ERROR_CAMERA_DEVICE:
case ERROR_CAMERA_SERVICE:
{
+ int32_t errorVal = ::ERROR_CAMERA_DEVICE;
+ // We keep this switch since this block might be encountered with
+ // more than just 2 states. The default fallthrough could have us
+ // handling more unmatched error cases.
switch (errorCode) {
case ERROR_CAMERA_DEVICE:
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
break;
case ERROR_CAMERA_SERVICE:
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ errorVal = ::ERROR_CAMERA_SERVICE;
break;
default:
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_UNKNOWN);
@@ -1309,7 +1314,7 @@
msg->setPointer(kContextKey, dev->mAppCallbacks.context);
msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onError);
- msg->setInt32(kErrorCodeKey, errorCode);
+ msg->setInt32(kErrorCodeKey, errorVal);
msg->post();
break;
}
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 1b8e8d9..7d3fbea 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -58,7 +58,36 @@
#include "Overlay.h"
#include "FrameOutput.h"
-using namespace android;
+using android::ABuffer;
+using android::ALooper;
+using android::AMessage;
+using android::AString;
+using android::DisplayInfo;
+using android::FrameOutput;
+using android::IBinder;
+using android::IGraphicBufferProducer;
+using android::ISurfaceComposer;
+using android::MediaCodec;
+using android::MediaCodecBuffer;
+using android::MediaMuxer;
+using android::Overlay;
+using android::PersistentSurface;
+using android::ProcessState;
+using android::Rect;
+using android::String8;
+using android::SurfaceComposerClient;
+using android::Vector;
+using android::sp;
+using android::status_t;
+
+using android::DISPLAY_ORIENTATION_0;
+using android::DISPLAY_ORIENTATION_180;
+using android::DISPLAY_ORIENTATION_90;
+using android::INFO_FORMAT_CHANGED;
+using android::INFO_OUTPUT_BUFFERS_CHANGED;
+using android::INVALID_OPERATION;
+using android::NO_ERROR;
+using android::UNKNOWN_ERROR;
static const uint32_t kMinBitRate = 100000; // 0.1Mbps
static const uint32_t kMaxBitRate = 200 * 1000000; // 200Mbps
diff --git a/include/media/VorbisComment.h b/include/media/VorbisComment.h
deleted file mode 120000
index adaa489..0000000
--- a/include/media/VorbisComment.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediaextractor/include/media/VorbisComment.h
\ No newline at end of file
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 6282793..eda7b61 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -10,11 +10,14 @@
shared_libs: [
"liblog",
"libmediaextractor",
+ "libmediandk",
],
static_libs: [
"libFLAC",
"libstagefright_foundation",
+ "libstagefright_metadatautils",
+ "libutils",
],
name: "libflacextractor",
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 337ada5..fcfdaff 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -25,7 +25,7 @@
#include "FLAC/stream_decoder.h"
#include <media/MediaExtractorPluginApi.h>
-#include <media/VorbisComment.h>
+#include <media/NdkMediaFormat.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h>
@@ -33,24 +33,25 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MetaDataUtils.h>
#include <media/stagefright/MediaBufferBase.h>
namespace android {
class FLACParser;
-class FLACSource : public MediaTrackHelper {
+class FLACSource : public MediaTrackHelperV2 {
public:
FLACSource(
DataSourceHelper *dataSource,
- MetaDataBase &meta);
+ AMediaFormat *meta);
- virtual status_t start();
- virtual status_t stop();
- virtual status_t getFormat(MetaDataBase &meta);
+ virtual media_status_t start();
+ virtual media_status_t stop();
+ virtual media_status_t getFormat(AMediaFormat *meta);
- virtual status_t read(
+ virtual media_status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
protected:
@@ -58,7 +59,7 @@
private:
DataSourceHelper *mDataSource;
- MetaDataBase mTrackMetadata;
+ AMediaFormat *mTrackMetadata;
FLACParser *mParser;
bool mInitCheck;
bool mStarted;
@@ -81,8 +82,8 @@
explicit FLACParser(
DataSourceHelper *dataSource,
// If metadata pointers aren't provided, we don't fill them
- MetaDataBase *fileMetadata = 0,
- MetaDataBase *trackMetadata = 0);
+ AMediaFormat *fileMetadata = 0,
+ AMediaFormat *trackMetadata = 0);
virtual ~FLACParser();
@@ -119,8 +120,8 @@
private:
DataSourceHelper *mDataSource;
- MetaDataBase *mFileMetadata;
- MetaDataBase *mTrackMetadata;
+ AMediaFormat *mFileMetadata;
+ AMediaFormat *mTrackMetadata;
bool mInitCheck;
// media buffers
@@ -364,9 +365,8 @@
case FLAC__METADATA_TYPE_PICTURE:
if (mFileMetadata != 0) {
const FLAC__StreamMetadata_Picture *p = &metadata->data.picture;
- mFileMetadata->setData(kKeyAlbumArt,
- MetaData::TYPE_NONE, p->data, p->data_length);
- mFileMetadata->setCString(kKeyAlbumArtMIME, p->mime_type);
+ AMediaFormat_setBuffer(mFileMetadata, AMEDIAFORMAT_KEY_ALBUMART,
+ p->data, p->data_length);
}
break;
default:
@@ -488,8 +488,8 @@
FLACParser::FLACParser(
DataSourceHelper *dataSource,
- MetaDataBase *fileMetadata,
- MetaDataBase *trackMetadata)
+ AMediaFormat *fileMetadata,
+ AMediaFormat *trackMetadata)
: mDataSource(dataSource),
mFileMetadata(fileMetadata),
mTrackMetadata(trackMetadata),
@@ -615,20 +615,25 @@
}
// populate track metadata
if (mTrackMetadata != 0) {
- mTrackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- mTrackMetadata->setInt32(kKeyChannelCount, getChannels());
- mTrackMetadata->setInt32(kKeySampleRate, getSampleRate());
- mTrackMetadata->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
+ AMediaFormat_setString(mTrackMetadata,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
+ AMediaFormat_setInt32(mTrackMetadata,
+ AMEDIAFORMAT_KEY_CHANNEL_COUNT, getChannels());
+ AMediaFormat_setInt32(mTrackMetadata,
+ AMEDIAFORMAT_KEY_SAMPLE_RATE, getSampleRate());
+ AMediaFormat_setInt32(mTrackMetadata,
+ AMEDIAFORMAT_KEY_PCM_ENCODING, kAudioEncodingPcm16bit);
// sample rate is non-zero, so division by zero not possible
- mTrackMetadata->setInt64(kKeyDuration,
- (getTotalSamples() * 1000000LL) / getSampleRate());
+ AMediaFormat_setInt64(mTrackMetadata,
+ AMEDIAFORMAT_KEY_DURATION, (getTotalSamples() * 1000000LL) / getSampleRate());
}
} else {
ALOGE("missing STREAMINFO");
return NO_INIT;
}
if (mFileMetadata != 0) {
- mFileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
+ AMediaFormat_setString(mFileMetadata,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
}
return OK;
}
@@ -709,7 +714,7 @@
FLACSource::FLACSource(
DataSourceHelper *dataSource,
- MetaDataBase &trackMetadata)
+ AMediaFormat *trackMetadata)
: mDataSource(dataSource),
mTrackMetadata(trackMetadata),
mParser(0),
@@ -731,7 +736,7 @@
delete mParser;
}
-status_t FLACSource::start()
+media_status_t FLACSource::start()
{
ALOGV("FLACSource::start");
@@ -739,10 +744,10 @@
mParser->allocateBuffers();
mStarted = true;
- return OK;
+ return AMEDIA_OK;
}
-status_t FLACSource::stop()
+media_status_t FLACSource::stop()
{
ALOGV("FLACSource::stop");
@@ -750,16 +755,15 @@
mParser->releaseBuffers();
mStarted = false;
- return OK;
+ return AMEDIA_OK;
}
-status_t FLACSource::getFormat(MetaDataBase &meta)
+media_status_t FLACSource::getFormat(AMediaFormat *meta)
{
- meta = mTrackMetadata;
- return OK;
+ return AMediaFormat_copy(meta, mTrackMetadata);
}
-status_t FLACSource::read(
+media_status_t FLACSource::read(
MediaBufferBase **outBuffer, const ReadOptions *options)
{
MediaBufferBase *buffer;
@@ -783,7 +787,7 @@
buffer = mParser->readBuffer();
}
*outBuffer = buffer;
- return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
+ return buffer != NULL ? AMEDIA_OK : AMEDIA_ERROR_END_OF_STREAM;
}
// FLACExtractor
@@ -796,7 +800,9 @@
{
ALOGV("FLACExtractor::FLACExtractor");
// FLACParser will fill in the metadata for us
- mParser = new FLACParser(mDataSource, &mFileMetadata, &mTrackMetadata);
+ mFileMetadata = AMediaFormat_new();
+ mTrackMetadata = AMediaFormat_new();
+ mParser = new FLACParser(mDataSource, mFileMetadata, mTrackMetadata);
mInitCheck = mParser->initCheck();
}
@@ -805,6 +811,8 @@
ALOGV("~FLACExtractor::FLACExtractor");
delete mParser;
delete mDataSource;
+ AMediaFormat_delete(mFileMetadata);
+ AMediaFormat_delete(mTrackMetadata);
}
size_t FLACExtractor::countTracks()
@@ -812,7 +820,7 @@
return mInitCheck == OK ? 1 : 0;
}
-MediaTrackHelper *FLACExtractor::getTrack(size_t index)
+MediaTrackHelperV2 *FLACExtractor::getTrack(size_t index)
{
if (mInitCheck != OK || index > 0) {
return NULL;
@@ -820,20 +828,18 @@
return new FLACSource(mDataSource, mTrackMetadata);
}
-status_t FLACExtractor::getTrackMetaData(
- MetaDataBase &meta,
+media_status_t FLACExtractor::getTrackMetaData(
+ AMediaFormat *meta,
size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index > 0) {
- return UNKNOWN_ERROR;
+ return AMEDIA_ERROR_UNKNOWN;
}
- meta = mTrackMetadata;
- return OK;
+ return AMediaFormat_copy(meta, mTrackMetadata);
}
-status_t FLACExtractor::getMetaData(MetaDataBase &meta)
+media_status_t FLACExtractor::getMetaData(AMediaFormat *meta)
{
- meta = mFileMetadata;
- return OK;
+ return AMediaFormat_copy(meta, mFileMetadata);
}
// Sniffer
@@ -862,22 +868,22 @@
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
- EXTRACTORDEF_VERSION,
+ EXTRACTORDEF_VERSION_CURRENT,
UUID("1364b048-cc45-4fda-9934-327d0ebf9829"),
1,
"FLAC Extractor",
{
- [](
+ .v2 = [](
CDataSource *source,
float *confidence,
void **,
- FreeMetaFunc *) -> CreatorFunc {
+ FreeMetaFunc *) -> CreatorFuncV2 {
DataSourceHelper helper(source);
if (SniffFLAC(&helper, confidence)) {
return [](
CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new FLACExtractor(new DataSourceHelper(source)));};
+ void *) -> CMediaExtractorV2* {
+ return wrapV2(new FLACExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 829f661..323307b 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -20,23 +20,23 @@
#include <media/DataSourceBase.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
-#include <media/stagefright/MetaDataBase.h>
+#include <media/NdkMediaFormat.h>
#include <utils/String8.h>
namespace android {
class FLACParser;
-class FLACExtractor : public MediaExtractorPluginHelper {
+class FLACExtractor : public MediaExtractorPluginHelperV2 {
public:
explicit FLACExtractor(DataSourceHelper *source);
virtual size_t countTracks();
- virtual MediaTrackHelper *getTrack(size_t index);
- virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
+ virtual MediaTrackHelperV2 *getTrack(size_t index);
+ virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
- virtual status_t getMetaData(MetaDataBase& meta);
+ virtual media_status_t getMetaData(AMediaFormat *meta);
virtual const char * name() { return "FLACExtractor"; }
protected:
@@ -46,10 +46,10 @@
DataSourceHelper *mDataSource;
FLACParser *mParser;
status_t mInitCheck;
- MetaDataBase mFileMetadata;
+ AMediaFormat *mFileMetadata;
// There is only one track
- MetaDataBase mTrackMetadata;
+ AMediaFormat *mTrackMetadata;
FLACExtractor(const FLACExtractor &);
FLACExtractor &operator=(const FLACExtractor &);
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index a3aeaca..1025c46 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -13,6 +13,7 @@
shared_libs: [
"liblog",
"libmediaextractor",
+ "libmediandk",
"libstagefright_foundation",
],
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index eca5711..621fd03 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -207,19 +207,19 @@
return valid;
}
-class MP3Source : public MediaTrackHelper {
+class MP3Source : public MediaTrackHelperV2 {
public:
MP3Source(
- MetaDataBase &meta, DataSourceHelper *source,
+ AMediaFormat *meta, DataSourceHelper *source,
off64_t first_frame_pos, uint32_t fixed_header,
MP3Seeker *seeker);
- virtual status_t start();
- virtual status_t stop();
+ virtual media_status_t start();
+ virtual media_status_t stop();
- virtual status_t getFormat(MetaDataBase &meta);
+ virtual media_status_t getFormat(AMediaFormat *meta);
- virtual status_t read(
+ virtual media_status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
protected:
@@ -227,7 +227,7 @@
private:
static const size_t kMaxFrameSize;
- MetaDataBase &mMeta;
+ AMediaFormat *mMeta;
DataSourceHelper *mDataSource;
off64_t mFirstFramePos;
uint32_t mFixedHeader;
@@ -283,6 +283,7 @@
mFixedHeader = header;
XINGSeeker *seeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
+ mMeta = AMediaFormat_new();
if (seeker == NULL) {
mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos);
} else {
@@ -290,8 +291,8 @@
int encd = seeker->getEncoderDelay();
int encp = seeker->getEncoderPadding();
if (encd != 0 || encp != 0) {
- mMeta.setInt32(kKeyEncoderDelay, encd);
- mMeta.setInt32(kKeyEncoderPadding, encp);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_ENCODER_DELAY, encd);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_ENCODER_PADDING, encp);
}
}
@@ -327,21 +328,23 @@
switch (layer) {
case 1:
- mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
+ AMediaFormat_setString(mMeta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
break;
case 2:
- mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+ AMediaFormat_setString(mMeta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
break;
case 3:
- mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
break;
default:
TRESPASS();
}
- mMeta.setInt32(kKeySampleRate, sample_rate);
- mMeta.setInt32(kKeyBitRate, bitrate * 1000);
- mMeta.setInt32(kKeyChannelCount, num_channels);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_BIT_RATE, bitrate * 1000);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, num_channels);
int64_t durationUs;
@@ -361,7 +364,7 @@
}
if (durationUs >= 0) {
- mMeta.setInt64(kKeyDuration, durationUs);
+ AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, durationUs);
}
mInitCheck = OK;
@@ -389,8 +392,8 @@
int32_t delay, padding;
if (sscanf(value, " %*x %x %x %*x", &delay, &padding) == 2) {
- mMeta.setInt32(kKeyEncoderDelay, delay);
- mMeta.setInt32(kKeyEncoderPadding, padding);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_ENCODER_DELAY, delay);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_ENCODER_PADDING, padding);
}
break;
}
@@ -404,13 +407,14 @@
MP3Extractor::~MP3Extractor() {
delete mSeeker;
delete mDataSource;
+ AMediaFormat_delete(mMeta);
}
size_t MP3Extractor::countTracks() {
return mInitCheck != OK ? 0 : 1;
}
-MediaTrackHelper *MP3Extractor::getTrack(size_t index) {
+MediaTrackHelperV2 *MP3Extractor::getTrack(size_t index) {
if (mInitCheck != OK || index != 0) {
return NULL;
}
@@ -420,14 +424,14 @@
mSeeker);
}
-status_t MP3Extractor::getTrackMetaData(
- MetaDataBase &meta,
+media_status_t MP3Extractor::getTrackMetaData(
+ AMediaFormat *meta,
size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index != 0) {
- return UNKNOWN_ERROR;
+ return AMEDIA_ERROR_UNKNOWN;
}
- meta = mMeta;
- return OK;
+ AMediaFormat_copy(meta, mMeta);
+ return AMEDIA_OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -440,7 +444,7 @@
// Set our max frame size to the nearest power of 2 above this size (aka, 4kB)
const size_t MP3Source::kMaxFrameSize = (1 << 12); /* 4096 bytes */
MP3Source::MP3Source(
- MetaDataBase &meta, DataSourceHelper *source,
+ AMediaFormat *meta, DataSourceHelper *source,
off64_t first_frame_pos, uint32_t fixed_header,
MP3Seeker *seeker)
: mMeta(meta),
@@ -462,7 +466,7 @@
}
}
-status_t MP3Source::start() {
+media_status_t MP3Source::start() {
CHECK(!mStarted);
mGroup = new MediaBufferGroup;
@@ -477,10 +481,10 @@
mStarted = true;
- return OK;
+ return AMEDIA_OK;
}
-status_t MP3Source::stop() {
+media_status_t MP3Source::stop() {
CHECK(mStarted);
delete mGroup;
@@ -488,15 +492,14 @@
mStarted = false;
- return OK;
+ return AMEDIA_OK;
}
-status_t MP3Source::getFormat(MetaDataBase &meta) {
- meta = mMeta;
- return OK;
+media_status_t MP3Source::getFormat(AMediaFormat *meta) {
+ return AMediaFormat_copy(meta, mMeta);
}
-status_t MP3Source::read(
+media_status_t MP3Source::read(
MediaBufferBase **out, const ReadOptions *options) {
*out = NULL;
@@ -509,11 +512,11 @@
if (mSeeker == NULL
|| !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) {
int32_t bitrate;
- if (!mMeta.findInt32(kKeyBitRate, &bitrate)) {
+ if (!AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate)) {
// bitrate is in bits/sec.
ALOGI("no bitrate");
- return ERROR_UNSUPPORTED;
+ return AMEDIA_ERROR_UNSUPPORTED;
}
mCurrentTimeUs = seekTimeUs;
@@ -530,7 +533,7 @@
MediaBufferBase *buffer;
status_t err = mGroup->acquire_buffer(&buffer);
if (err != OK) {
- return err;
+ return AMEDIA_ERROR_UNKNOWN;
}
size_t frame_size;
@@ -543,7 +546,7 @@
buffer->release();
buffer = NULL;
- return (n < 0 ? n : ERROR_END_OF_STREAM);
+ return (n < 0 ? AMEDIA_ERROR_UNKNOWN : AMEDIA_ERROR_END_OF_STREAM);
}
uint32_t header = U32_AT((const uint8_t *)buffer->data());
@@ -572,7 +575,7 @@
buffer->release();
buffer = NULL;
- return ERROR_END_OF_STREAM;
+ return AMEDIA_ERROR_END_OF_STREAM;
}
mCurrentPos = pos;
@@ -587,7 +590,7 @@
buffer->release();
buffer = NULL;
- return (n < 0 ? n : ERROR_END_OF_STREAM);
+ return (n < 0 ? AMEDIA_ERROR_UNKNOWN : AMEDIA_ERROR_END_OF_STREAM);
}
buffer->set_range(0, frame_size);
@@ -602,40 +605,40 @@
*out = buffer;
- return OK;
+ return AMEDIA_OK;
}
-status_t MP3Extractor::getMetaData(MetaDataBase &meta) {
- meta.clear();
+media_status_t MP3Extractor::getMetaData(AMediaFormat *meta) {
+ AMediaFormat_clear(meta);
if (mInitCheck != OK) {
- return UNKNOWN_ERROR;
+ return AMEDIA_ERROR_UNKNOWN;
}
- meta.setCString(kKeyMIMEType, "audio/mpeg");
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, "audio/mpeg");
DataSourceHelper helper(mDataSource);
ID3 id3(&helper);
if (!id3.isValid()) {
- return OK;
+ return AMEDIA_OK;
}
struct Map {
- int key;
+ const char *key;
const char *tag1;
const char *tag2;
};
static const Map kMap[] = {
- { kKeyAlbum, "TALB", "TAL" },
- { kKeyArtist, "TPE1", "TP1" },
- { kKeyAlbumArtist, "TPE2", "TP2" },
- { kKeyComposer, "TCOM", "TCM" },
- { kKeyGenre, "TCON", "TCO" },
- { kKeyTitle, "TIT2", "TT2" },
- { kKeyYear, "TYE", "TYER" },
- { kKeyAuthor, "TXT", "TEXT" },
- { kKeyCDTrackNumber, "TRK", "TRCK" },
- { kKeyDiscNumber, "TPA", "TPOS" },
- { kKeyCompilation, "TCP", "TCMP" },
+ { AMEDIAFORMAT_KEY_ALBUM, "TALB", "TAL" },
+ { AMEDIAFORMAT_KEY_ARTIST, "TPE1", "TP1" },
+ { AMEDIAFORMAT_KEY_ALBUMARTIST, "TPE2", "TP2" },
+ { AMEDIAFORMAT_KEY_COMPOSER, "TCOM", "TCM" },
+ { AMEDIAFORMAT_KEY_GENRE, "TCON", "TCO" },
+ { AMEDIAFORMAT_KEY_TITLE, "TIT2", "TT2" },
+ { AMEDIAFORMAT_KEY_YEAR, "TYE", "TYER" },
+ { AMEDIAFORMAT_KEY_AUTHOR, "TXT", "TEXT" },
+ { AMEDIAFORMAT_KEY_CDTRACKNUMBER, "TRK", "TRCK" },
+ { AMEDIAFORMAT_KEY_DISCNUMBER, "TPA", "TPOS" },
+ { AMEDIAFORMAT_KEY_COMPILATION, "TCP", "TCMP" },
};
static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
@@ -655,7 +658,7 @@
it->getString(&s);
delete it;
- meta.setCString(kMap[i].key, s);
+ AMediaFormat_setString(meta, kMap[i].key, s.string());
}
size_t dataSize;
@@ -663,21 +666,20 @@
const void *data = id3.getAlbumArt(&dataSize, &mime);
if (data) {
- meta.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
- meta.setCString(kKeyAlbumArtMIME, mime.string());
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_ALBUMART, data, dataSize);
}
- return OK;
+ return AMEDIA_OK;
}
-static CMediaExtractor* CreateExtractor(
+static CMediaExtractorV2* CreateExtractor(
CDataSource *source,
void *meta) {
Mp3Meta *metaData = static_cast<Mp3Meta *>(meta);
- return wrap(new MP3Extractor(new DataSourceHelper(source), metaData));
+ return wrapV2(new MP3Extractor(new DataSourceHelper(source), metaData));
}
-static CreatorFunc Sniff(
+static CreatorFuncV2 Sniff(
CDataSource *source, float *confidence, void **meta,
FreeMetaFunc *freeMeta) {
off64_t pos = 0;
@@ -714,11 +716,11 @@
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
- EXTRACTORDEF_VERSION,
+ EXTRACTORDEF_VERSION_CURRENT,
UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
1, // version
"MP3 Extractor",
- { Sniff }
+ { .v2 = Sniff }
};
}
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 92e0665..22547e2 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -21,7 +21,7 @@
#include <utils/Errors.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
-#include <media/stagefright/MetaDataBase.h>
+#include <media/NdkMediaFormat.h>
namespace android {
@@ -32,16 +32,16 @@
class String8;
struct Mp3Meta;
-class MP3Extractor : public MediaExtractorPluginHelper {
+class MP3Extractor : public MediaExtractorPluginHelperV2 {
public:
MP3Extractor(DataSourceHelper *source, Mp3Meta *meta);
~MP3Extractor();
virtual size_t countTracks();
- virtual MediaTrackHelper *getTrack(size_t index);
- virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
+ virtual MediaTrackHelperV2 *getTrack(size_t index);
+ virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
- virtual status_t getMetaData(MetaDataBase& meta);
+ virtual media_status_t getMetaData(AMediaFormat *meta);
virtual const char * name() { return "MP3Extractor"; }
private:
@@ -49,7 +49,7 @@
DataSourceHelper *mDataSource;
off64_t mFirstFramePos;
- MetaDataBase mMeta;
+ AMediaFormat *mMeta;
uint32_t mFixedHeader;
MP3Seeker *mSeeker;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index e81e9b2..eec0392 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -3608,7 +3608,6 @@
if (data) {
mFileMetaData.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
- mFileMetaData.setCString(kKeyAlbumArtMIME, mime.string());
}
}
}
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 7c6fc75..c6deb18 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -10,10 +10,12 @@
shared_libs: [
"liblog",
"libmediaextractor",
+ "libmediandk",
],
static_libs: [
"libstagefright_foundation",
+ "libstagefright_metadatautils",
"libutils",
"libvorbisidec",
],
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 123ac91..1b4fe27 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -24,7 +24,6 @@
#include <utils/Vector.h>
#include <media/DataSourceBase.h>
#include <media/ExtractorUtils.h>
-#include <media/VorbisComment.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h>
@@ -34,6 +33,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaDataBase.h>
+#include <media/stagefright/MetaDataUtils.h>
#include <utils/String8.h>
extern "C" {
@@ -47,15 +47,15 @@
namespace android {
-struct OggSource : public MediaTrackHelper {
+struct OggSource : public MediaTrackHelperV2 {
explicit OggSource(OggExtractor *extractor);
- virtual status_t getFormat(MetaDataBase &);
+ virtual media_status_t getFormat(AMediaFormat *);
- virtual status_t start();
- virtual status_t stop();
+ virtual media_status_t start();
+ virtual media_status_t stop();
- virtual status_t read(
+ virtual media_status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
protected:
@@ -77,7 +77,7 @@
int64_t seekPreRollUs);
virtual ~MyOggExtractor();
- status_t getFormat(MetaDataBase &) const;
+ media_status_t getFormat(AMediaFormat *) const;
// Returns an approximate bitrate in bits per second.
virtual uint64_t approxBitrate() const = 0;
@@ -88,9 +88,8 @@
status_t init();
- status_t getFileMetaData(MetaDataBase &meta) {
- meta = mFileMeta;
- return OK;
+ media_status_t getFileMetaData(AMediaFormat *meta) {
+ return AMediaFormat_copy(meta, mFileMeta);
}
protected:
@@ -129,8 +128,8 @@
vorbis_info mVi;
vorbis_comment mVc;
- MetaDataBase mMeta;
- MetaDataBase mFileMeta;
+ AMediaFormat *mMeta;
+ AMediaFormat *mFileMeta;
Vector<TOCEntry> mTableOfContents;
@@ -237,27 +236,27 @@
}
}
-status_t OggSource::getFormat(MetaDataBase &meta) {
+media_status_t OggSource::getFormat(AMediaFormat *meta) {
return mExtractor->mImpl->getFormat(meta);
}
-status_t OggSource::start() {
+media_status_t OggSource::start() {
if (mStarted) {
- return INVALID_OPERATION;
+ return AMEDIA_ERROR_INVALID_OPERATION;
}
mStarted = true;
- return OK;
+ return AMEDIA_OK;
}
-status_t OggSource::stop() {
+media_status_t OggSource::stop() {
mStarted = false;
- return OK;
+ return AMEDIA_OK;
}
-status_t OggSource::read(
+media_status_t OggSource::read(
MediaBufferBase **out, const ReadOptions *options) {
*out = NULL;
@@ -266,7 +265,7 @@
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
status_t err = mExtractor->mImpl->seekToTime(seekTimeUs);
if (err != OK) {
- return err;
+ return AMEDIA_ERROR_UNKNOWN;
}
}
@@ -274,7 +273,7 @@
status_t err = mExtractor->mImpl->readNextPacket(&packet);
if (err != OK) {
- return err;
+ return AMEDIA_ERROR_UNKNOWN;
}
#if 0
@@ -290,7 +289,7 @@
*out = packet;
- return OK;
+ return AMEDIA_OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -316,16 +315,19 @@
vorbis_info_init(&mVi);
vorbis_comment_init(&mVc);
+ mMeta = AMediaFormat_new();
+ mFileMeta = AMediaFormat_new();
}
MyOggExtractor::~MyOggExtractor() {
+ AMediaFormat_delete(mFileMeta);
+ AMediaFormat_delete(mMeta);
vorbis_comment_clear(&mVc);
vorbis_info_clear(&mVi);
}
-status_t MyOggExtractor::getFormat(MetaDataBase &meta) const {
- meta = mMeta;
- return OK;
+media_status_t MyOggExtractor::getFormat(AMediaFormat *meta) const {
+ return AMediaFormat_copy(meta, mMeta);
}
status_t MyOggExtractor::findNextPage(
@@ -832,7 +834,7 @@
}
status_t MyOggExtractor::init() {
- mMeta.setCString(kKeyMIMEType, mMimeType);
+ AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType);
status_t err;
MediaBufferBase *packet;
@@ -865,7 +867,7 @@
int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
- mMeta.setInt64(kKeyDuration, durationUs);
+ AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, durationUs);
buildTableOfContents();
}
@@ -981,11 +983,14 @@
mChannelCount = data[9];
mCodecDelay = U16LE_AT(&data[10]);
- mMeta.setData(kKeyOpusHeader, 0, data, size);
- mMeta.setInt32(kKeySampleRate, kOpusSampleRate);
- mMeta.setInt32(kKeyChannelCount, mChannelCount);
- mMeta.setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
- mMeta.setInt64(kKeyOpusCodecDelay /* ns */,
+ // kKeyOpusHeader is csd-0
+ AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, kOpusSampleRate);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mChannelCount);
+ // are these actually used anywhere?
+ // (they are kKeyOpusSeekPreRoll and kKeyOpusCodecDelay respectively)
+ AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_2, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
+ AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1,
mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
return OK;
@@ -1122,10 +1127,10 @@
return ERROR_MALFORMED;
}
- mMeta.setData(kKeyVorbisInfo, 0, data, size);
- mMeta.setInt32(kKeySampleRate, mVi.rate);
- mMeta.setInt32(kKeyChannelCount, mVi.channels);
- mMeta.setInt32(kKeyBitRate, mVi.bitrate_nominal);
+ AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, mVi.rate);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mVi.channels);
+ AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_BIT_RATE, mVi.bitrate_nominal);
ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
@@ -1140,7 +1145,7 @@
if (mSource->getSize(&size) == OK) {
uint64_t bps = approxBitrate();
if (bps != 0) {
- mMeta.setInt64(kKeyDuration, size * 8000000ll / bps);
+ AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, size * 8000000ll / bps);
}
}
break;
@@ -1162,7 +1167,7 @@
return ERROR_MALFORMED;
}
- mMeta.setData(kKeyVorbisBooks, 0, data, size);
+ AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size);
break;
}
}
@@ -1180,12 +1185,12 @@
void MyOggExtractor::parseFileMetaData() {
- mFileMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
+ AMediaFormat_setString(mFileMeta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_OGG);
for (int i = 0; i < mVc.comments; ++i) {
const char *comment = mVc.user_comments[i];
size_t commentLength = mVc.comment_lengths[i];
- parseVorbisComment(&mFileMeta, comment, commentLength);
+ parseVorbisComment(mFileMeta, comment, commentLength);
//ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
}
}
@@ -1227,7 +1232,7 @@
return mInitCheck != OK ? 0 : 1;
}
-MediaTrackHelper *OggExtractor::getTrack(size_t index) {
+MediaTrackHelperV2 *OggExtractor::getTrack(size_t index) {
if (index >= 1) {
return NULL;
}
@@ -1235,27 +1240,27 @@
return new OggSource(this);
}
-status_t OggExtractor::getTrackMetaData(
- MetaDataBase &meta,
+media_status_t OggExtractor::getTrackMetaData(
+ AMediaFormat *meta,
size_t index, uint32_t /* flags */) {
if (index >= 1) {
- return UNKNOWN_ERROR;
+ return AMEDIA_ERROR_UNKNOWN;
}
return mImpl->getFormat(meta);
}
-status_t OggExtractor::getMetaData(MetaDataBase &meta) {
+media_status_t OggExtractor::getMetaData(AMediaFormat *meta) {
return mImpl->getFileMetaData(meta);
}
-static CMediaExtractor* CreateExtractor(
+static CMediaExtractorV2* CreateExtractor(
CDataSource *source,
void *) {
- return wrap(new OggExtractor(new DataSourceHelper(source)));
+ return wrapV2(new OggExtractor(new DataSourceHelper(source)));
}
-static CreatorFunc Sniff(
+static CreatorFuncV2 Sniff(
CDataSource *source,
float *confidence,
void **,
@@ -1276,11 +1281,11 @@
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
- EXTRACTORDEF_VERSION,
+ EXTRACTORDEF_VERSION_CURRENT,
UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
1, // version
"Ogg Extractor",
- { Sniff }
+ { .v2 = Sniff }
};
}
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index c70f832..cd674f3 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -21,6 +21,7 @@
#include <utils/Errors.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
+#include <media/NdkMediaFormat.h>
namespace android {
@@ -30,14 +31,14 @@
struct MyOggExtractor;
struct OggSource;
-struct OggExtractor : public MediaExtractorPluginHelper {
+struct OggExtractor : public MediaExtractorPluginHelperV2 {
explicit OggExtractor(DataSourceHelper *source);
virtual size_t countTracks();
- virtual MediaTrackHelper *getTrack(size_t index);
- virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
+ virtual MediaTrackHelperV2 *getTrack(size_t index);
+ virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
- virtual status_t getMetaData(MetaDataBase& meta);
+ virtual media_status_t getMetaData(AMediaFormat *meta);
virtual const char * name() { return "OggExtractor"; }
protected:
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index ef272b0..319467e 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -19,6 +19,18 @@
}
cc_test {
+ name: "test_clock_model",
+ defaults: ["libaaudio_tests_defaults"],
+ srcs: ["test_clock_model.cpp"],
+ shared_libs: [
+ "libaaudio",
+ "libaudioutils",
+ "libcutils",
+ "libutils",
+ ],
+}
+
+cc_test {
name: "test_block_adapter",
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_block_adapter.cpp"],
diff --git a/media/libaaudio/tests/test_clock_model.cpp b/media/libaaudio/tests/test_clock_model.cpp
new file mode 100644
index 0000000..3c09025
--- /dev/null
+++ b/media/libaaudio/tests/test_clock_model.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Unit tests for Isochronous Clock Model
+
+#include <math.h>
+#include <stdlib.h>
+
+
+#include <aaudio/AAudio.h>
+#include <audio_utils/clock.h>
+#include <client/IsochronousClockModel.h>
+#include <gtest/gtest.h>
+
+using namespace aaudio;
+
+// We can use arbitrary values here because we are not opening a real audio stream.
+#define SAMPLE_RATE 48000
+#define HW_FRAMES_PER_BURST 48
+#define NANOS_PER_BURST (NANOS_PER_SECOND * HW_FRAMES_PER_BURST / SAMPLE_RATE)
+
+class ClockModelTestFixture: public ::testing::Test {
+public:
+ ClockModelTestFixture() {
+ }
+
+ void SetUp() {
+ model.setSampleRate(SAMPLE_RATE);
+ model.setFramesPerBurst(HW_FRAMES_PER_BURST);
+ }
+
+ void TearDown() {
+
+ }
+
+ ~ClockModelTestFixture() {
+ // cleanup any pending stuff, but no exceptions allowed
+ }
+
+ IsochronousClockModel model;
+};
+
+// Check default setup.
+TEST_F(ClockModelTestFixture, clock_setup) {
+ ASSERT_EQ(SAMPLE_RATE, model.getSampleRate());
+ ASSERT_EQ(HW_FRAMES_PER_BURST, model.getFramesPerBurst());
+}
+
+// Test delta calculations.
+TEST_F(ClockModelTestFixture, clock_deltas) {
+ int64_t position = model.convertDeltaTimeToPosition(NANOS_PER_SECOND);
+ ASSERT_EQ(SAMPLE_RATE, position);
+
+ // Deltas are not quantized.
+ // Compare time to the equivalent position in frames.
+ constexpr int64_t kNanosPerBurst = HW_FRAMES_PER_BURST * NANOS_PER_SECOND / SAMPLE_RATE;
+ position = model.convertDeltaTimeToPosition(NANOS_PER_SECOND + (kNanosPerBurst / 2));
+ ASSERT_EQ(SAMPLE_RATE + (HW_FRAMES_PER_BURST / 2), position);
+
+ int64_t time = model.convertDeltaPositionToTime(SAMPLE_RATE);
+ ASSERT_EQ(NANOS_PER_SECOND, time);
+
+ // Compare position in frames to the equivalent time.
+ time = model.convertDeltaPositionToTime(SAMPLE_RATE + (HW_FRAMES_PER_BURST / 2));
+ ASSERT_EQ(NANOS_PER_SECOND + (kNanosPerBurst / 2), time);
+}
+
+// start() should force the internal markers
+TEST_F(ClockModelTestFixture, clock_start) {
+ const int64_t startTime = 100000;
+ model.start(startTime);
+
+ int64_t position = model.convertTimeToPosition(startTime);
+ EXPECT_EQ(0, position);
+
+ int64_t time = model.convertPositionToTime(position);
+ EXPECT_EQ(startTime, time);
+
+ time = startTime + (500 * NANOS_PER_MICROSECOND);
+ position = model.convertTimeToPosition(time);
+ EXPECT_EQ(0, position);
+}
+
+// timestamps moves the window if outside the bounds
+// TODO test nudging the window
+TEST_F(ClockModelTestFixture, clock_timestamp) {
+ const int64_t startTime = 100000000;
+ model.start(startTime);
+
+ const int64_t position = HW_FRAMES_PER_BURST; // hardware
+ int64_t markerTime = startTime + NANOS_PER_MILLISECOND + (200 * NANOS_PER_MICROSECOND);
+
+ // Should set marker.
+ model.processTimestamp(position, markerTime);
+ EXPECT_EQ(position, model.convertTimeToPosition(markerTime));
+
+ // convertTimeToPosition rounds down
+ EXPECT_EQ(position, model.convertTimeToPosition(markerTime + (73 * NANOS_PER_MICROSECOND)));
+
+ // convertPositionToTime rounds up
+ EXPECT_EQ(markerTime + NANOS_PER_BURST, model.convertPositionToTime(position + 17));
+}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 34c5428..038c854 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1300,10 +1300,7 @@
mNewPosition = position + mUpdatePeriod;
status_t result = createRecord_l(position, mOpPackageName);
- if (result != NO_ERROR) {
- ALOGW("%s(%d): createRecord_l failed, do not retry", __func__, mId);
- retries = 0;
- } else {
+ if (result == NO_ERROR) {
if (mActive) {
// callback thread or sync event hasn't changed
// FIXME this fails if we have a new AudioFlinger instance
@@ -1316,13 +1313,15 @@
if (result != NO_ERROR) {
ALOGW("%s(%d): failed status %d, retries %d", __func__, mId, result, retries);
if (--retries > 0) {
+ // leave time for an eventual race condition to clear before retrying
+ usleep(500000);
goto retry;
}
- }
-
- if (result != NO_ERROR) {
- ALOGW("%s(%d): failed status %d", __func__, mId, result);
- mActive = false;
+ // if no retries left, set invalid bit to force restoring at next occasion
+ // and avoid inconsistent active state on client and server sides
+ if (mCblk != nullptr) {
+ android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
+ }
}
return result;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index e77abc6..c86d4ce 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2308,10 +2308,7 @@
// If a new IAudioTrack cannot be created, the previous (dead) instance will be left intact.
status_t result = createTrack_l();
- if (result != NO_ERROR) {
- ALOGW("%s(%d): createTrack_l failed, do not retry", __func__, mId);
- retries = 0;
- } else {
+ if (result == NO_ERROR) {
// take the frames that will be lost by track recreation into account in saved position
// For streaming tracks, this is the amount we obtained from the user/client
// (not the number actually consumed at the server - those are already lost).
@@ -2358,12 +2355,16 @@
if (result != NO_ERROR) {
ALOGW("%s(%d): failed status %d, retries %d", __func__, mId, result, retries);
if (--retries > 0) {
+ // leave time for an eventual race condition to clear before retrying
+ usleep(500000);
goto retry;
}
- mState = STATE_STOPPED;
- mReleased = 0;
+ // if no retries left, set invalid bit to force restoring at next occasion
+ // and avoid inconsistent active state on client and server sides
+ if (mCblk != nullptr) {
+ android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
+ }
}
-
return result;
}
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 93fb667..25d28ff 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -153,7 +153,7 @@
filegroup {
name: "mediaupdateservice_aidl",
srcs: [
- "aidl/android/media/IMediaExtractorUpdateService.aidl",
+ "aidl/android/media/IMediaUpdateService.aidl",
],
}
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 7d67262..9e09c7e 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -1244,37 +1244,15 @@
return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
}
-ssize_t AMediaDataSourceWrapper::AMediaDataSourceWrapper_getSize(void *userdata) {
- DataSource *source = static_cast<DataSource *>(userdata);
- off64_t size = -1;
- source->getSize(&size);
- return size;
-}
-
-ssize_t AMediaDataSourceWrapper::AMediaDataSourceWrapper_readAt(void *userdata, off64_t offset, void * buf, size_t size) {
- DataSource *source = static_cast<DataSource *>(userdata);
- return source->readAt(offset, buf, size);
-}
-
-void AMediaDataSourceWrapper::AMediaDataSourceWrapper_close(void *userdata) {
- DataSource *source = static_cast<DataSource *>(userdata);
- source->close();
-}
-
-AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
- : mDataSource(dataSource),
- mAMediaDataSource(AMediaDataSource_new()) {
- ALOGV("setDataSource (source: %p)", dataSource.get());
- AMediaDataSource_setUserdata(mAMediaDataSource, dataSource.get());
- AMediaDataSource_setReadAt(mAMediaDataSource, AMediaDataSourceWrapper_readAt);
- AMediaDataSource_setGetSize(mAMediaDataSource, AMediaDataSourceWrapper_getSize);
- AMediaDataSource_setClose(mAMediaDataSource, AMediaDataSourceWrapper_close);
+AMediaDataSourceWrapper::AMediaDataSourceWrapper(AMediaDataSource *aDataSource)
+ : mAMediaDataSource(aDataSource) {
}
AMediaDataSourceWrapper::~AMediaDataSourceWrapper() {
if (mAMediaDataSource == NULL) {
return;
}
+ AMediaDataSource_close(mAMediaDataSource);
AMediaDataSource_delete(mAMediaDataSource);
mAMediaDataSource = NULL;
}
@@ -1283,4 +1261,8 @@
return mAMediaDataSource;
}
+void AMediaDataSourceWrapper::close() {
+ AMediaDataSource_close(mAMediaDataSource);
+}
+
} // namespace android
diff --git a/media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl b/media/libmedia/aidl/android/media/IMediaUpdateService.aidl
similarity index 84%
rename from media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl
rename to media/libmedia/aidl/android/media/IMediaUpdateService.aidl
index 57b1bc9..4777969 100644
--- a/media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl
+++ b/media/libmedia/aidl/android/media/IMediaUpdateService.aidl
@@ -17,9 +17,9 @@
package android.media;
/**
- * Service to reload extractor plugins when update package is installed/uninstalled.
+ * Service to reload media component plugins when update package is installed/uninstalled.
* @hide
*/
-interface IMediaExtractorUpdateService {
+interface IMediaUpdateService {
void loadPlugins(@utf8InCpp String apkPath);
}
diff --git a/media/libmedia/include/media/NdkWrapper.h b/media/libmedia/include/media/NdkWrapper.h
index 191665a..b3b0688 100644
--- a/media/libmedia/include/media/NdkWrapper.h
+++ b/media/libmedia/include/media/NdkWrapper.h
@@ -278,6 +278,30 @@
DISALLOW_EVIL_CONSTRUCTORS(AMediaCodecWrapper);
};
+struct AMediaDataSourceWrapper : public RefBase {
+
+ AMediaDataSourceWrapper(AMediaDataSource*);
+ AMediaDataSourceWrapper(int fd, int64_t offset, int64_t length);
+
+ AMediaDataSource *getAMediaDataSource();
+ int getFd() { return mFd; }
+ int64_t getOffset() { return mOffset; }
+ int64_t getLength() { return mLength; }
+
+ void close();
+
+protected:
+ virtual ~AMediaDataSourceWrapper();
+
+private:
+ AMediaDataSource *mAMediaDataSource;
+ int mFd;
+ int64_t mOffset;
+ int64_t mLength;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AMediaDataSourceWrapper);
+};
+
struct AMediaExtractorWrapper : public RefBase {
AMediaExtractorWrapper(AMediaExtractor *aMediaExtractor);
@@ -337,31 +361,6 @@
DISALLOW_EVIL_CONSTRUCTORS(AMediaExtractorWrapper);
};
-struct AMediaDataSourceWrapper : public RefBase {
-
- static status_t translate_error(media_status_t err);
-
- static ssize_t AMediaDataSourceWrapper_getSize(void *userdata);
-
- static ssize_t AMediaDataSourceWrapper_readAt(void *userdata, off64_t offset, void * buf, size_t size);
-
- static void AMediaDataSourceWrapper_close(void *userdata);
-
- AMediaDataSourceWrapper(const sp<DataSource> &dataSource);
-
- AMediaDataSource *getAMediaDataSource();
-
-protected:
- virtual ~AMediaDataSourceWrapper();
-
-private:
- sp<DataSource> mDataSource;
-
- AMediaDataSource *mAMediaDataSource;
-
- DISALLOW_EVIL_CONSTRUCTORS(AMediaDataSourceWrapper);
-};
-
} // namespace android
#endif // NDK_WRAPPER_H_
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 4ffbb69..0871d60 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -38,7 +38,6 @@
"MediaSource.cpp",
"MetaData.cpp",
"MetaDataBase.cpp",
- "VorbisComment.cpp",
],
clang: true,
diff --git a/media/libmediaextractor/VorbisComment.cpp b/media/libmediaextractor/VorbisComment.cpp
deleted file mode 100644
index fabaf51..0000000
--- a/media/libmediaextractor/VorbisComment.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisComment"
-#include <utils/Log.h>
-
-#include "media/VorbisComment.h"
-
-#include <media/stagefright/foundation/base64.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/ByteUtils.h>
-#include <media/stagefright/MetaDataBase.h>
-
-namespace android {
-
-static void extractAlbumArt(
- MetaDataBase *fileMeta, const void *data, size_t size) {
- ALOGV("extractAlbumArt from '%s'", (const char *)data);
-
- sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
- if (flacBuffer == NULL) {
- ALOGE("malformed base64 encoded data.");
- return;
- }
-
- size_t flacSize = flacBuffer->size();
- uint8_t *flac = flacBuffer->data();
- ALOGV("got flac of size %zu", flacSize);
-
- uint32_t picType;
- uint32_t typeLen;
- uint32_t descLen;
- uint32_t dataLen;
- char type[128];
-
- if (flacSize < 8) {
- return;
- }
-
- picType = U32_AT(flac);
-
- if (picType != 3) {
- // This is not a front cover.
- return;
- }
-
- typeLen = U32_AT(&flac[4]);
- if (typeLen > sizeof(type) - 1) {
- return;
- }
-
- // we've already checked above that flacSize >= 8
- if (flacSize - 8 < typeLen) {
- return;
- }
-
- memcpy(type, &flac[8], typeLen);
- type[typeLen] = '\0';
-
- ALOGV("picType = %d, type = '%s'", picType, type);
-
- if (!strcmp(type, "-->")) {
- // This is not inline cover art, but an external url instead.
- return;
- }
-
- if (flacSize < 32 || flacSize - 32 < typeLen) {
- return;
- }
-
- descLen = U32_AT(&flac[8 + typeLen]);
- if (flacSize - 32 - typeLen < descLen) {
- return;
- }
-
- dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
-
- // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
- if (flacSize - 32 - typeLen - descLen < dataLen) {
- return;
- }
-
- ALOGV("got image data, %zu trailing bytes",
- flacSize - 32 - typeLen - descLen - dataLen);
-
- fileMeta->setData(
- kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
-
- fileMeta->setCString(kKeyAlbumArtMIME, type);
-}
-
-void parseVorbisComment(
- MetaDataBase *fileMeta, const char *comment, size_t commentLength)
-{
- struct {
- const char *const mTag;
- uint32_t mKey;
- } kMap[] = {
- { "TITLE", kKeyTitle },
- { "ARTIST", kKeyArtist },
- { "ALBUMARTIST", kKeyAlbumArtist },
- { "ALBUM ARTIST", kKeyAlbumArtist },
- { "COMPILATION", kKeyCompilation },
- { "ALBUM", kKeyAlbum },
- { "COMPOSER", kKeyComposer },
- { "GENRE", kKeyGenre },
- { "AUTHOR", kKeyAuthor },
- { "TRACKNUMBER", kKeyCDTrackNumber },
- { "DISCNUMBER", kKeyDiscNumber },
- { "DATE", kKeyDate },
- { "YEAR", kKeyYear },
- { "LYRICIST", kKeyWriter },
- { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
- { "ANDROID_LOOP", kKeyAutoLoop },
- };
-
- for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
- size_t tagLen = strlen(kMap[j].mTag);
- if (!strncasecmp(kMap[j].mTag, comment, tagLen)
- && comment[tagLen] == '=') {
- if (kMap[j].mKey == kKeyAlbumArt) {
- extractAlbumArt(
- fileMeta,
- &comment[tagLen + 1],
- commentLength - tagLen - 1);
- } else if (kMap[j].mKey == kKeyAutoLoop) {
- if (!strcasecmp(&comment[tagLen + 1], "true")) {
- fileMeta->setInt32(kKeyAutoLoop, true);
- }
- } else {
- fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
- }
- }
- }
-
-}
-
-} // namespace android
diff --git a/media/libmediaextractor/include/media/VorbisComment.h b/media/libmediaextractor/include/media/VorbisComment.h
deleted file mode 100644
index 8ba3295..0000000
--- a/media/libmediaextractor/include/media/VorbisComment.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef VORBIS_COMMENT_H_
-#define VORBIS_COMMENT_H_
-
-namespace android {
-
-class MetaDataBase;
-
-void parseVorbisComment(
- MetaDataBase *fileMeta, const char *comment, size_t commentLength);
-
-} // namespace android
-
-#endif // VORBIS_COMMENT_H_
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
index fa5c723..0a99974 100644
--- a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
@@ -101,7 +101,6 @@
kKeyTitle = 'titl', // cstring
kKeyYear = 'year', // cstring
kKeyAlbumArt = 'albA', // compressed image data
- kKeyAlbumArtMIME = 'alAM', // cstring
kKeyAuthor = 'auth', // cstring
kKeyCDTrackNumber = 'cdtr', // cstring
kKeyDiscNumber = 'dnum', // cstring
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index a26cc81..75d1df0 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -28,6 +28,7 @@
"libcrypto",
"libmediametrics",
"libmediandk",
+ "libmediandk_utils",
"libmediautils",
"libmemunreachable",
"libnativewindow",
diff --git a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
index 9dd5e4c..6b27ca7 100644
--- a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
+++ b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
@@ -44,8 +44,8 @@
String8 result;
result.append(" MediaPlayer2AudioOutput\n");
- snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
- mStreamType, mLeftVolume, mRightVolume);
+ snprintf(buffer, 255, " stream type(%d), volume(%f)\n",
+ mStreamType, mVolume);
result.append(buffer);
snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
@@ -67,8 +67,7 @@
mCallbackCookie(NULL),
mCallbackData(NULL),
mStreamType(AUDIO_STREAM_MUSIC),
- mLeftVolume(1.0),
- mRightVolume(1.0),
+ mVolume(1.0),
mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
mSampleRateHz(0),
mMsecsPerFrame(0),
@@ -402,7 +401,7 @@
mCallbackData = newcbd;
ALOGV("setVolume");
- t->setVolume(mLeftVolume, mRightVolume);
+ t->setVolume(mVolume);
mSampleRateHz = sampleRate;
mFlags = flags;
@@ -444,7 +443,7 @@
mCallbackData->endTrackSwitch();
}
if (mTrack != 0) {
- mTrack->setVolume(mLeftVolume, mRightVolume);
+ mTrack->setVolume(mVolume);
mTrack->setAuxEffectSendLevel(mSendLevel);
status_t status = mTrack->start();
return status;
@@ -498,13 +497,12 @@
// destruction of the track occurs outside of mutex.
}
-void MediaPlayer2AudioOutput::setVolume(float left, float right) {
- ALOGV("setVolume(%f, %f)", left, right);
+void MediaPlayer2AudioOutput::setVolume(float volume) {
+ ALOGV("setVolume(%f)", volume);
Mutex::Autolock lock(mLock);
- mLeftVolume = left;
- mRightVolume = right;
+ mVolume = volume;
if (mTrack != 0) {
- mTrack->setVolume(left, right);
+ mTrack->setVolume(volume);
}
}
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
index ee67abf..fe1005b 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
@@ -77,7 +77,7 @@
}
void setAudioAttributes(const audio_attributes_t * attributes);
- void setVolume(float left, float right);
+ void setVolume(float volume);
virtual status_t setPlaybackRate(const AudioPlaybackRate& rate);
virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */);
@@ -113,8 +113,7 @@
CallbackData * mCallbackData;
audio_stream_type_t mStreamType;
audio_attributes_t * mAttributes;
- float mLeftVolume;
- float mRightVolume;
+ float mVolume;
AudioPlaybackRate mPlaybackRate;
uint32_t mSampleRateHz; // sample rate of the content, as set in open()
float mMsecsPerFrame;
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index 18254a1..4f73ad3 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -88,7 +88,7 @@
status_t getAudioStreamType(audio_stream_type_t *type);
status_t setLooping(int loop);
bool isLooping();
- status_t setVolume(float leftVolume, float rightVolume);
+ status_t setVolume(float volume);
void notify(int64_t srcId, int msg, int ext1, int ext2,
const PlayerMessage *obj = NULL);
status_t invoke(const PlayerMessage &request, PlayerMessage *reply);
@@ -142,8 +142,7 @@
audio_stream_type_t mStreamType;
Parcel* mAudioAttributesParcel;
bool mLoop;
- float mLeftVolume;
- float mRightVolume;
+ float mVolume;
int mVideoWidth;
int mVideoHeight;
audio_session_t mAudioSessionId;
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index d9c9826..3b155c5 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -321,7 +321,7 @@
mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
mCurrentState = MEDIA_PLAYER2_IDLE;
mLoop = false;
- mLeftVolume = mRightVolume = 1.0;
+ mVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
@@ -403,6 +403,15 @@
if (dsd == NULL) {
return BAD_VALUE;
}
+ // Microsecond is used in NuPlayer2.
+ if (dsd->mStartPositionMs > INT64_MAX / 1000) {
+ dsd->mStartPositionMs = INT64_MAX / 1000;
+ ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
+ }
+ if (dsd->mEndPositionMs > INT64_MAX / 1000) {
+ dsd->mEndPositionMs = INT64_MAX / 1000;
+ ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
+ }
ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
sp<MediaPlayer2Interface> oldPlayer;
@@ -630,7 +639,7 @@
mPlayer->setLooping(mLoop);
if (mAudioOutput != 0) {
- mAudioOutput->setVolume(mLeftVolume, mRightVolume);
+ mAudioOutput->setVolume(mVolume);
}
if (mAudioOutput != 0) {
@@ -968,13 +977,12 @@
return false;
}
-status_t MediaPlayer2::setVolume(float leftVolume, float rightVolume) {
- ALOGV("MediaPlayer2::setVolume(%f, %f)", leftVolume, rightVolume);
+status_t MediaPlayer2::setVolume(float volume) {
+ ALOGV("MediaPlayer2::setVolume(%f)", volume);
Mutex::Autolock _l(mLock);
- mLeftVolume = leftVolume;
- mRightVolume = rightVolume;
+ mVolume = volume;
if (mAudioOutput != 0) {
- mAudioOutput->setVolume(leftVolume, rightVolume);
+ mAudioOutput->setVolume(volume);
}
return OK;
}
diff --git a/media/libmediaplayer2/nuplayer2/Android.bp b/media/libmediaplayer2/nuplayer2/Android.bp
index 26da491..c3c94b6 100644
--- a/media/libmediaplayer2/nuplayer2/Android.bp
+++ b/media/libmediaplayer2/nuplayer2/Android.bp
@@ -28,6 +28,7 @@
"frameworks/av/media/libstagefright/mpeg2ts",
"frameworks/av/media/libstagefright/rtsp",
"frameworks/av/media/libstagefright/timedtext",
+ "frameworks/av/media/ndk",
],
cflags: [
@@ -49,6 +50,7 @@
"libgui",
"libmedia",
"libmediandk",
+ "libmediandk_utils",
"libpowermanager",
],
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index 4ce1a88..6056ad9 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -21,29 +21,20 @@
#include "NuPlayer2Drm.h"
#include "AnotherPacketSource.h"
-#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <media/DataSource.h>
#include <media/MediaBufferHolder.h>
-#include <media/IMediaExtractorService.h>
-#include <media/IMediaSource.h>
-#include <media/MediaHTTPService.h>
-#include <media/MediaSource.h>
#include <media/NdkWrapper.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/ClearDataSourceFactory.h>
-#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaClock.h>
#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/NdkUtils.h>
#include <media/stagefright/Utils.h>
-#include "../../libstagefright/include/NuCachedSource2.h"
-#include "../../libstagefright/include/HTTPBase.h"
+#include "NdkMediaDataSourceCallbacksPriv.h"
namespace android {
@@ -88,9 +79,6 @@
void NuPlayer2::GenericSource2::resetDataSource() {
ALOGV("resetDataSource");
- mHTTPService.clear();
- mHttpSource.clear();
- mDisconnected = false;
mUri.clear();
mUriHeaders.clear();
if (mFd >= 0) {
@@ -109,7 +97,6 @@
}
status_t NuPlayer2::GenericSource2::setDataSource(
- const sp<MediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers) {
Mutex::Autolock _l(mLock);
@@ -117,7 +104,6 @@
resetDataSource();
- mHTTPService = httpService;
mUri = url;
if (headers) {
@@ -150,7 +136,8 @@
ALOGV("setDataSource (source: %p)", source.get());
resetDataSource();
- mDataSource = source;
+ AMediaDataSource *aSource = convertDataSourceToAMediaDataSource(source);
+ mDataSourceWrapper = new AMediaDataSourceWrapper(aSource);
return OK;
}
@@ -161,24 +148,21 @@
status_t NuPlayer2::GenericSource2::initFromDataSource() {
mExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
- CHECK(mDataSource != NULL || mFd != -1);
- sp<DataSource> dataSource = mDataSource;
+ CHECK(mFd >=0 || mDataSourceWrapper != NULL);
+ sp<AMediaDataSourceWrapper> aSourceWrapper = mDataSourceWrapper;
const int fd = mFd;
- const int64_t offset = mOffset;
- const int64_t length = mLength;
mLock.unlock();
// This might take long time if data source is not reliable.
status_t err;
- if (dataSource != nullptr) {
- mDataSourceWrapper = new AMediaDataSourceWrapper(dataSource);
- err = mExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
+ if (aSourceWrapper != NULL) {
+ err = mExtractor->setDataSource(aSourceWrapper->getAMediaDataSource());
} else {
- err = mExtractor->setDataSource(fd, offset, length);
+ err = mExtractor->setDataSource(fd, mOffset, mLength);
}
if (err != OK) {
- ALOGE("initFromDataSource, failed to create data source!");
+ ALOGE("initFromDataSource, failed to set extractor data source!");
mLock.lock();
return UNKNOWN_ERROR;
}
@@ -190,10 +174,8 @@
return UNKNOWN_ERROR;
}
- mLock.lock();
- mFd = -1;
- mDataSource = dataSource;
mFileMeta = convertMediaFormatWrapperToMetaData(mExtractor->getFormat());
+ mLock.lock();
if (mFileMeta != NULL) {
int64_t duration;
if (mFileMeta->findInt64(kKeyDuration, &duration)) {
@@ -214,11 +196,7 @@
}
sp<AMediaExtractorWrapper> trackExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
- if (mDataSourceWrapper != nullptr) {
- err = trackExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
- } else {
- err = trackExtractor->setDataSource(fd, offset, length);
- }
+ trackExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
const char *mime;
sp<MetaData> meta = convertMediaFormatWrapperToMetaData(trackFormat);
@@ -329,13 +307,13 @@
mLooper->unregisterHandler(id());
mLooper->stop();
}
- if (mDataSource != NULL) {
- mDataSource->close();
+ if (mDataSourceWrapper != NULL) {
+ mDataSourceWrapper->close();
}
resetDataSource();
}
-void NuPlayer2::GenericSource2::prepareAsync() {
+void NuPlayer2::GenericSource2::prepareAsync(int64_t startTimeUs) {
Mutex::Autolock _l(mLock);
ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
@@ -350,59 +328,45 @@
}
sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
+ msg->setInt64("startTimeUs", startTimeUs);
+
msg->post();
}
-void NuPlayer2::GenericSource2::onPrepareAsync() {
- ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
+void NuPlayer2::GenericSource2::onPrepareAsync(int64_t startTimeUs) {
+ ALOGV("onPrepareAsync: mFd %d mUri %s mDataSourceWrapper: %p",
+ mFd, mUri.c_str(), mDataSourceWrapper.get());
- // delayed data source creation
- if (mDataSource == NULL) {
- // set to false first, if the extractor
- // comes back as secure, set it to true then.
- mIsSecure = false;
-
- if (!mUri.empty()) {
- const char* uri = mUri.c_str();
- String8 contentType;
-
- if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
- mHttpSource = ClearDataSourceFactory::CreateMediaHTTP(mHTTPService);
- if (mHttpSource == NULL) {
- ALOGE("Failed to create http source!");
- notifyPreparedAndCleanup(UNKNOWN_ERROR);
- return;
- }
- }
-
- mLock.unlock();
- // This might take long time if connection has some issue.
- sp<DataSource> dataSource = ClearDataSourceFactory::CreateFromURI(
- mHTTPService, uri, &mUriHeaders, &contentType,
- static_cast<HTTPBase *>(mHttpSource.get()));
- mLock.lock();
- if (!mDisconnected) {
- mDataSource = dataSource;
- }
+ if (!mUri.empty()) {
+ const char* uri = mUri.c_str();
+ size_t numheaders = mUriHeaders.size();
+ const char **key_values = numheaders ? new const char *[numheaders * 2] : NULL;
+ for (size_t i = 0; i < numheaders; ++i) {
+ key_values[i * 2] = mUriHeaders.keyAt(i).c_str();
+ key_values[i * 2 + 1] = mUriHeaders.valueAt(i).c_str();
}
-
- if (mFd == -1 && mDataSource == NULL) {
- ALOGE("Failed to create data source!");
- notifyPreparedAndCleanup(UNKNOWN_ERROR);
- return;
- }
+ mLock.unlock();
+ AMediaDataSource *aSource = AMediaDataSource_newUri(uri, numheaders, key_values);
+ mLock.lock();
+ mDataSourceWrapper = aSource ? new AMediaDataSourceWrapper(aSource) : NULL;
+ delete[] key_values;
+ // For cached streaming cases, we need to wait for enough
+ // buffering before reporting prepared.
+ mIsStreaming = !strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8);
}
- if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
- mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
+ if (mDisconnected || (mFd < 0 && mDataSourceWrapper == NULL)) {
+ ALOGE("mDisconnected(%d) or Failed to create data source!", mDisconnected);
+ notifyPreparedAndCleanup(UNKNOWN_ERROR);
+ return;
}
- // For cached streaming cases, we need to wait for enough
- // buffering before reporting prepared.
- mIsStreaming = (mCachedSource != NULL);
-
// init extractor from data source
status_t err = initFromDataSource();
+ if (mFd >= 0) {
+ close(mFd);
+ mFd = -1;
+ }
if (err != OK) {
ALOGE("Failed to init from data source!");
@@ -429,6 +393,7 @@
FLAG_CAN_SEEK_FORWARD |
FLAG_CAN_SEEK);
+ doSeek(startTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
finishPrepareAsync();
ALOGV("onPrepareAsync: Done");
@@ -438,8 +403,8 @@
ALOGV("finishPrepareAsync");
if (mIsStreaming) {
- mCachedSource->resumeFetchingIfNecessary();
mPreparing = true;
+ ++mPollBufferingGeneration;
schedulePollBuffering();
} else {
notifyPrepared();
@@ -456,9 +421,7 @@
void NuPlayer2::GenericSource2::notifyPreparedAndCleanup(status_t err) {
if (err != OK) {
- mDataSource.clear();
- mCachedSource.clear();
- mHttpSource.clear();
+ mDataSourceWrapper.clear();
mBitrate = -1;
mPrevBufferPercentage = -1;
@@ -498,53 +461,27 @@
}
void NuPlayer2::GenericSource2::disconnect() {
- sp<DataSource> dataSource, httpSource;
{
Mutex::Autolock _l(mLock);
- dataSource = mDataSource;
- httpSource = mHttpSource;
mDisconnected = true;
}
-
- if (dataSource != NULL) {
- // disconnect data source
- if (dataSource->flags() & DataSource::kIsCachingDataSource) {
- static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
- }
- } else if (httpSource != NULL) {
- static_cast<HTTPBase *>(httpSource.get())->disconnect();
+ if (mDataSourceWrapper != NULL) {
+ mDataSourceWrapper->close();
}
-
- mDataSourceWrapper = NULL;
-
}
status_t NuPlayer2::GenericSource2::feedMoreTSData() {
return OK;
}
-void NuPlayer2::GenericSource2::sendCacheStats() {
- int32_t kbps = 0;
- status_t err = UNKNOWN_ERROR;
-
- if (mCachedSource != NULL) {
- err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
- }
-
- if (err == OK) {
- sp<AMessage> notify = dupNotify();
- notify->setInt32("what", kWhatCacheStats);
- notify->setInt32("bandwidth", kbps);
- notify->post();
- }
-}
-
void NuPlayer2::GenericSource2::onMessageReceived(const sp<AMessage> &msg) {
Mutex::Autolock _l(mLock);
switch (msg->what()) {
case kWhatPrepareAsync:
{
- onPrepareAsync();
+ int64_t startTimeUs;
+ CHECK(msg->findInt64("startTimeUs", &startTimeUs));
+ onPrepareAsync(startTimeUs);
break;
}
case kWhatFetchSubtitleData:
@@ -834,8 +771,6 @@
}
if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
&& !mSentPauseOnBuffering && !mPreparing) {
- mCachedSource->resumeFetchingIfNecessary();
- sendCacheStats();
mSentPauseOnBuffering = true;
sp<AMessage> notify = dupNotify();
notify->setInt32("what", kWhatPauseOnBufferingStart);
@@ -1391,7 +1326,6 @@
notifyPrepared();
mPreparing = false;
} else {
- sendCacheStats();
mSentPauseOnBuffering = false;
sp<AMessage> notify = dupNotify();
notify->setInt32("what", kWhatResumeOnBufferingEnd);
@@ -1443,47 +1377,31 @@
}
void NuPlayer2::GenericSource2::schedulePollBuffering() {
- sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
- msg->setInt32("generation", mPollBufferingGeneration);
- // Enquires buffering status every second.
- msg->post(1000000ll);
+ if (mIsStreaming) {
+ sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
+ msg->setInt32("generation", mPollBufferingGeneration);
+ // Enquires buffering status every second.
+ msg->post(1000000ll);
+ }
}
void NuPlayer2::GenericSource2::onPollBuffering() {
- status_t finalStatus = UNKNOWN_ERROR;
int64_t cachedDurationUs = -1ll;
- ssize_t cachedDataRemaining = -1;
- if (mCachedSource != NULL) {
- cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
-
- if (finalStatus == OK) {
- off64_t size;
- int64_t bitrate = 0ll;
- if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
- // |bitrate| uses bits/second unit, while size is number of bytes.
- bitrate = size * 8000000ll / mDurationUs;
- } else if (mBitrate > 0) {
- bitrate = mBitrate;
- }
- if (bitrate > 0) {
- cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
- }
- }
+ sp<AMediaExtractorWrapper> extractor;
+ if (mVideoTrack.mExtractor != NULL) {
+ extractor = mVideoTrack.mExtractor;
+ } else if (mAudioTrack.mExtractor != NULL) {
+ extractor = mAudioTrack.mExtractor;
}
- if (finalStatus != OK) {
- ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
-
- if (finalStatus == ERROR_END_OF_STREAM) {
- notifyBufferingUpdate(100);
- }
-
- return;
+ if (extractor != NULL) {
+ cachedDurationUs = extractor->getCachedDuration();
}
if (cachedDurationUs >= 0ll) {
- if (mDurationUs > 0ll) {
+ ssize_t sampleSize = extractor->getSampleSize();
+ if (sampleSize >= 0ll) {
int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
int percentage = 100.0 * cachedPosUs / mDurationUs;
if (percentage > 100) {
@@ -1491,9 +1409,11 @@
}
notifyBufferingUpdate(percentage);
+ ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
+ } else {
+ notifyBufferingUpdate(100);
+ ALOGV("onPollBuffering: EOS");
}
-
- ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
}
schedulePollBuffering();
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.h b/media/libmediaplayer2/nuplayer2/GenericSource2.h
index 9bc5182..ade1aa3 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.h
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.h
@@ -37,11 +37,9 @@
class DataSource;
class IDataSource;
class IMediaSource;
-struct MediaHTTPService;
struct MediaSource;
class MediaBuffer;
struct MediaClock;
-struct NuCachedSource2;
struct NuPlayer2::GenericSource2 : public NuPlayer2::Source,
public MediaBufferObserver // Modular DRM
@@ -50,7 +48,6 @@
const sp<MediaClock> &mediaClock);
status_t setDataSource(
- const sp<MediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers);
@@ -62,7 +59,7 @@
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
- virtual void prepareAsync();
+ virtual void prepareAsync(int64_t startTimeUs);
virtual void start();
virtual void stop();
@@ -151,7 +148,6 @@
bool mIsStreaming;
uid_t mUID;
const sp<MediaClock> mMediaClock;
- sp<MediaHTTPService> mHTTPService;
AString mUri;
KeyedVector<String8, String8> mUriHeaders;
int mFd;
@@ -159,9 +155,6 @@
int64_t mLength;
bool mDisconnected;
- sp<DataSource> mDataSource;
- sp<NuCachedSource2> mCachedSource;
- sp<DataSource> mHttpSource;
sp<MetaData> mFileMeta;
sp<AMediaDataSourceWrapper> mDataSourceWrapper;
sp<AMediaExtractorWrapper> mExtractor;
@@ -194,7 +187,7 @@
void onSeek(const sp<AMessage>& msg);
status_t doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode);
- void onPrepareAsync();
+ void onPrepareAsync(int64_t startTimeUs);
void fetchTextData(
uint32_t what, media_track_type type,
@@ -232,8 +225,6 @@
void onPollBuffering();
void notifyBufferingUpdate(int32_t percentage);
- void sendCacheStats();
-
sp<AMessage> getFormat_l(bool audio);
sp<MetaData> getFormatMeta_l(bool audio);
int32_t getDataGeneration(media_track_type type) const;
diff --git a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
index a61cacd..175be53 100644
--- a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
@@ -99,7 +99,8 @@
return OK;
}
-void NuPlayer2::HTTPLiveSource2::prepareAsync() {
+// TODO: fetch data starting from |startTimeUs|
+void NuPlayer2::HTTPLiveSource2::prepareAsync(int64_t /* startTimeUs */) {
if (mLiveLooper == NULL) {
mLiveLooper = new ALooper;
mLiveLooper->setName("http live");
diff --git a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h
index 97d3653..8fc71e2 100644
--- a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h
+++ b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h
@@ -38,7 +38,7 @@
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
- virtual void prepareAsync();
+ virtual void prepareAsync(int64_t startTimeUs);
virtual void start();
virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 5bd1674..018324e 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -212,7 +212,6 @@
: mPID(pid),
mUID(uid),
mMediaClock(mediaClock),
- mSourceFlags(0),
mOffloadAudio(false),
mAudioDecoderGeneration(0),
mVideoDecoderGeneration(0),
@@ -240,8 +239,7 @@
mPaused(false),
mPausedByClient(true),
mPausedForBuffering(false),
- mIsDrmProtected(false),
- mDataSourceType(DATA_SOURCE_TYPE_NONE) {
+ mIsDrmProtected(false) {
CHECK(mediaClock != NULL);
clearFlushComplete();
}
@@ -309,7 +307,7 @@
sp<GenericSource2> genericSource =
new GenericSource2(notify, mUID, mMediaClock);
- err = genericSource->setDataSource(httpService, url, headers);
+ err = genericSource->setDataSource(url, headers);
if (err == OK) {
*source = genericSource;
@@ -393,11 +391,13 @@
// Now, source != NULL.
*/
- mDataSourceType = dataSourceType;
+ mCurrentSourceInfo.mDataSourceType = dataSourceType;
sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
msg->setObject("source", source);
msg->setInt64("srcId", dsd->mId);
+ msg->setInt64("startTimeUs", dsd->mStartPositionMs * 1000);
+ msg->setInt64("endTimeUs", dsd->mEndPositionMs * 1000);
msg->post();
}
@@ -415,11 +415,13 @@
// Now, source != NULL.
*/
- mNextDataSourceType = dataSourceType;
+ mNextSourceInfo.mDataSourceType = dataSourceType;
sp<AMessage> msg = new AMessage(kWhatPrepareNextDataSource, this);
msg->setObject("source", source);
msg->setInt64("srcId", dsd->mId);
+ msg->setInt64("startTimeUs", dsd->mStartPositionMs * 1000);
+ msg->setInt64("endTimeUs", dsd->mEndPositionMs * 1000);
msg->post();
}
@@ -554,7 +556,7 @@
sp<Source> source;
{
Mutex::Autolock autoLock(mSourceLock);
- source = mSource;
+ source = mCurrentSourceInfo.mSource;
}
if (source != NULL) {
@@ -640,15 +642,17 @@
{
ALOGV("kWhatSetDataSource");
- CHECK(mSource == NULL);
+ CHECK(mCurrentSourceInfo.mSource == NULL);
status_t err = OK;
sp<RefBase> obj;
CHECK(msg->findObject("source", &obj));
if (obj != NULL) {
Mutex::Autolock autoLock(mSourceLock);
- CHECK(msg->findInt64("srcId", &mSrcId));
- mSource = static_cast<Source *>(obj.get());
+ CHECK(msg->findInt64("srcId", &mCurrentSourceInfo.mSrcId));
+ CHECK(msg->findInt64("startTimeUs", &mCurrentSourceInfo.mStartTimeUs));
+ CHECK(msg->findInt64("endTimeUs", &mCurrentSourceInfo.mEndTimeUs));
+ mCurrentSourceInfo.mSource = static_cast<Source *>(obj.get());
} else {
err = UNKNOWN_ERROR;
ALOGE("kWhatSetDataSource, source should not be NULL");
@@ -657,7 +661,7 @@
CHECK(mDriver != NULL);
sp<NuPlayer2Driver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifySetDataSourceCompleted(mSrcId, err);
+ driver->notifySetDataSourceCompleted(mCurrentSourceInfo.mSrcId, err);
}
break;
}
@@ -671,9 +675,11 @@
CHECK(msg->findObject("source", &obj));
if (obj != NULL) {
Mutex::Autolock autoLock(mSourceLock);
- CHECK(msg->findInt64("srcId", &mNextSrcId));
- mNextSource = static_cast<Source *>(obj.get());
- mNextSource->prepareAsync();
+ CHECK(msg->findInt64("srcId", &mNextSourceInfo.mSrcId));
+ CHECK(msg->findInt64("startTimeUs", &mNextSourceInfo.mStartTimeUs));
+ CHECK(msg->findInt64("endTimeUs", &mNextSourceInfo.mEndTimeUs));
+ mNextSourceInfo.mSource = static_cast<Source *>(obj.get());
+ mNextSourceInfo.mSource->prepareAsync(mNextSourceInfo.mStartTimeUs);
} else {
err = UNKNOWN_ERROR;
}
@@ -686,7 +692,7 @@
ALOGV("kWhatPlayNextDataSource");
int64_t srcId;
CHECK(msg->findInt64("srcId", &srcId));
- if (srcId != mNextSrcId) {
+ if (srcId != mNextSourceInfo.mSrcId) {
notifyListener(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, 0);
return;
}
@@ -715,8 +721,8 @@
ALOGV("kWhatGetBufferingSettings");
BufferingSettings buffering;
status_t err = OK;
- if (mSource != NULL) {
- err = mSource->getBufferingSettings(&buffering);
+ if (mCurrentSourceInfo.mSource != NULL) {
+ err = mCurrentSourceInfo.mSource->getBufferingSettings(&buffering);
} else {
err = INVALID_OPERATION;
}
@@ -738,8 +744,8 @@
BufferingSettings buffering;
readFromAMessage(msg, &buffering);
status_t err = OK;
- if (mSource != NULL) {
- err = mSource->setBufferingSettings(buffering);
+ if (mCurrentSourceInfo.mSource != NULL) {
+ err = mCurrentSourceInfo.mSource->setBufferingSettings(buffering);
} else {
err = INVALID_OPERATION;
}
@@ -753,7 +759,7 @@
{
ALOGV("onMessageReceived kWhatPrepare");
- mSource->prepareAsync();
+ mCurrentSourceInfo.mSource->prepareAsync(mCurrentSourceInfo.mStartTimeUs);
break;
}
@@ -766,8 +772,8 @@
CHECK(msg->findPointer("reply", (void**)&reply));
size_t inbandTracks = 0;
- if (mSource != NULL) {
- inbandTracks = mSource->getTrackCount();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
}
size_t ccTracks = 0;
@@ -780,7 +786,7 @@
// write inband tracks
for (size_t i = 0; i < inbandTracks; ++i) {
- writeTrackInfo(reply, mSource->getTrackInfo(i));
+ writeTrackInfo(reply, mCurrentSourceInfo.mSource->getTrackInfo(i));
}
// write CC track
@@ -796,13 +802,13 @@
case kWhatGetSelectedTrack:
{
status_t err = INVALID_OPERATION;
- if (mSource != NULL) {
+ if (mCurrentSourceInfo.mSource != NULL) {
err = OK;
int32_t type32;
CHECK(msg->findInt32("type", (int32_t*)&type32));
media_track_type type = (media_track_type)type32;
- ssize_t selectedTrack = mSource->getSelectedTrack(type);
+ ssize_t selectedTrack = mCurrentSourceInfo.mSource->getSelectedTrack(type);
PlayerMessage* reply;
CHECK(msg->findPointer("reply", (void**)&reply));
@@ -833,8 +839,8 @@
status_t err = INVALID_OPERATION;
size_t inbandTracks = 0;
- if (mSource != NULL) {
- inbandTracks = mSource->getTrackCount();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
}
size_t ccTracks = 0;
if (mCCDecoder != NULL) {
@@ -842,11 +848,11 @@
}
if (trackIndex < inbandTracks) {
- err = mSource->selectTrack(trackIndex, select, timeUs);
+ err = mCurrentSourceInfo.mSource->selectTrack(trackIndex, select, timeUs);
if (!select && err == OK) {
int32_t type;
- sp<AMessage> info = mSource->getTrackInfo(trackIndex);
+ sp<AMessage> info = mCurrentSourceInfo.mSource->getTrackInfo(trackIndex);
if (info != NULL
&& info->findInt32("type", &type)
&& type == MEDIA_TRACK_TYPE_TIMEDTEXT) {
@@ -879,10 +885,10 @@
}
int64_t durationUs;
- if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
+ if (mDriver != NULL && mCurrentSourceInfo.mSource->getDuration(&durationUs) == OK) {
sp<NuPlayer2Driver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifyDuration(mSrcId, durationUs);
+ driver->notifyDuration(mCurrentSourceInfo.mSrcId, durationUs);
}
}
@@ -899,13 +905,15 @@
ALOGD("onSetVideoSurface(%p, %s video decoder)",
(nww == NULL ? NULL : nww->getANativeWindow()),
- (mSource != NULL && mStarted && mSource->getFormat(false /* audio */) != NULL
+ (mCurrentSourceInfo.mSource != NULL && mStarted
+ && mCurrentSourceInfo.mSource->getFormat(false /* audio */) != NULL
&& mVideoDecoder != NULL) ? "have" : "no");
- // Need to check mStarted before calling mSource->getFormat because NuPlayer2 might
- // be in preparing state and it could take long time.
- // When mStarted is true, mSource must have been set.
- if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL
+ // Need to check mStarted before calling mCurrentSourceInfo.mSource->getFormat
+ // because NuPlayer2 might be in preparing state and it could take long time.
+ // When mStarted is true, mCurrentSourceInfo.mSource must have been set.
+ if (mCurrentSourceInfo.mSource == NULL || !mStarted
+ || mCurrentSourceInfo.mSource->getFormat(false /* audio */) == NULL
// NOTE: mVideoDecoder's mNativeWindow is always non-null
|| (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(nww) == OK)) {
performSetSurface(nww);
@@ -972,7 +980,7 @@
onStart(true /* play */);
}
mPausedByClient = false;
- notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_STARTED, 0, 0);
break;
}
@@ -1130,21 +1138,22 @@
&& (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
// This is the first time we've found anything playable.
- if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
+ if (mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
schedulePollDuration();
}
}
status_t err;
- if ((err = mSource->feedMoreTSData()) != OK) {
+ if ((err = mCurrentSourceInfo.mSource->feedMoreTSData()) != OK) {
if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
// We're not currently decoding anything (no audio or
// video tracks found) and we just ran out of input data.
if (err == ERROR_END_OF_STREAM) {
- notifyListener(mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
} else {
- notifyListener(mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
+ notifyListener(
+ mCurrentSourceInfo.mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
}
}
break;
@@ -1226,10 +1235,10 @@
CHECK(msg->findMessage("format", &format));
sp<AMessage> inputFormat =
- mSource->getFormat(false /* audio */);
+ mCurrentSourceInfo.mSource->getFormat(false /* audio */);
setVideoScalingMode(mVideoScalingMode);
- updateVideoSize(mSrcId, inputFormat, format);
+ updateVideoSize(mCurrentSourceInfo.mSrcId, inputFormat, format);
} else if (what == DecoderBase::kWhatShutdownCompleted) {
ALOGV("%s shutdown completed", audio ? "audio" : "video");
if (audio) {
@@ -1296,28 +1305,39 @@
finishFlushIfPossible(); // Should not occur.
break; // Finish anyways.
}
- if (mSource != nullptr) {
+ if (mCurrentSourceInfo.mSource != nullptr) {
if (audio) {
- if (mVideoDecoderError || mSource->getFormat(false /* audio */) == NULL
- || mNativeWindow == NULL || mNativeWindow->getANativeWindow() == NULL
+ if (mVideoDecoderError
+ || mCurrentSourceInfo.mSource->getFormat(false /* audio */) == NULL
+ || mNativeWindow == NULL
+ || mNativeWindow->getANativeWindow() == NULL
|| mVideoDecoder == NULL) {
// When both audio and video have error, or this stream has only audio
// which has error, notify client of error.
- notifyListener(mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
+ notifyListener(
+ mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
+ MEDIA2_ERROR_UNKNOWN, err);
} else {
// Only audio track has error. Video track could be still good to play.
- notifyListener(mSrcId, MEDIA2_INFO, MEDIA2_INFO_PLAY_AUDIO_ERROR, err);
+ notifyListener(
+ mCurrentSourceInfo.mSrcId, MEDIA2_INFO,
+ MEDIA2_INFO_PLAY_AUDIO_ERROR, err);
}
mAudioDecoderError = true;
} else {
- if (mAudioDecoderError || mSource->getFormat(true /* audio */) == NULL
+ if (mAudioDecoderError
+ || mCurrentSourceInfo.mSource->getFormat(true /* audio */) == NULL
|| mAudioSink == NULL || mAudioDecoder == NULL) {
// When both audio and video have error, or this stream has only video
// which has error, notify client of error.
- notifyListener(mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
+ notifyListener(
+ mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
+ MEDIA2_ERROR_UNKNOWN, err);
} else {
// Only video track has error. Audio track could be still good to play.
- notifyListener(mSrcId, MEDIA2_INFO, MEDIA2_INFO_PLAY_VIDEO_ERROR, err);
+ notifyListener(
+ mCurrentSourceInfo.mSrcId, MEDIA2_INFO,
+ MEDIA2_INFO_PLAY_VIDEO_ERROR, err);
}
mVideoDecoderError = true;
}
@@ -1367,12 +1387,13 @@
audio ? "audio" : "video", finalResult);
notifyListener(
- mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, finalResult);
+ mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
+ MEDIA2_ERROR_UNKNOWN, finalResult);
}
if ((mAudioEOS || mAudioDecoder == NULL)
&& (mVideoEOS || mVideoDecoder == NULL)) {
- notifyListener(mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
}
} else if (what == Renderer::kWhatFlushComplete) {
int32_t audio;
@@ -1393,10 +1414,11 @@
handleFlushComplete(audio, false /* isDecoder */);
finishFlushIfPossible();
} else if (what == Renderer::kWhatVideoRenderingStart) {
- notifyListener(mSrcId, MEDIA2_INFO, MEDIA2_INFO_VIDEO_RENDERING_START, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_INFO,
+ MEDIA2_INFO_VIDEO_RENDERING_START, 0);
} else if (what == Renderer::kWhatMediaRenderingStart) {
ALOGV("media rendering started");
- notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_STARTED, 0, 0);
} else if (what == Renderer::kWhatAudioTearDown) {
int32_t reason;
CHECK(msg->findInt32("reason", &reason));
@@ -1449,7 +1471,7 @@
int64_t timerUs;
CHECK(msg->findInt64("timerUs", &timerUs));
- notifyListener(mSrcId, MEDIA2_NOTIFY_TIME, timerUs, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_NOTIFY_TIME, timerUs, 0);
break;
}
@@ -1468,20 +1490,20 @@
if (!mStarted) {
if (!mSourceStarted) {
mSourceStarted = true;
- mSource->start();
+ mCurrentSourceInfo.mSource->start();
}
if (seekTimeUs > 0) {
performSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
}
if (needNotify) {
- notifyDriverSeekComplete(mSrcId);
+ notifyDriverSeekComplete(mCurrentSourceInfo.mSrcId);
}
break;
}
// seeks can take a while, so we essentially paused
- notifyListener(mSrcId, MEDIA2_PAUSED, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PAUSED, 0, 0);
mDeferredActions.push_back(
new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
@@ -1506,7 +1528,7 @@
onStart(false /* play */);
}
onPause();
- notifyListener(mSrcId, MEDIA2_PAUSED, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PAUSED, 0, 0);
mPausedByClient = true;
break;
}
@@ -1559,8 +1581,8 @@
return;
}
mPaused = false;
- if (mSource != NULL) {
- mSource->resume();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ mCurrentSourceInfo.mSource->resume();
} else {
ALOGW("resume called when source is gone or not set");
}
@@ -1583,7 +1605,7 @@
if (!mSourceStarted) {
mSourceStarted = true;
- mSource->start();
+ mCurrentSourceInfo.mSource->start();
}
mOffloadAudio = false;
@@ -1594,22 +1616,23 @@
uint32_t flags = 0;
- if (mSource->isRealTime()) {
+ if (mCurrentSourceInfo.mSource->isRealTime()) {
flags |= Renderer::FLAG_REAL_TIME;
}
- bool hasAudio = (mSource->getFormat(true /* audio */) != NULL);
- bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
+ bool hasAudio = (mCurrentSourceInfo.mSource->getFormat(true /* audio */) != NULL);
+ bool hasVideo = (mCurrentSourceInfo.mSource->getFormat(false /* audio */) != NULL);
if (!hasAudio && !hasVideo) {
ALOGE("no metadata for either audio or video source");
- mSource->stop();
+ mCurrentSourceInfo.mSource->stop();
mSourceStarted = false;
- notifyListener(mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, ERROR_MALFORMED);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
+ MEDIA2_ERROR_UNKNOWN, ERROR_MALFORMED);
return;
}
ALOGV_IF(!hasAudio, "no metadata for audio source"); // video only stream
- sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
+ sp<MetaData> audioMeta = mCurrentSourceInfo.mSource->getFormatMeta(true /* audio */);
audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
if (mAudioSink != NULL) {
@@ -1617,7 +1640,7 @@
}
mOffloadAudio =
- canOffloadStream(audioMeta, hasVideo, mSource->isStreaming(), streamType)
+ canOffloadStream(audioMeta, hasVideo, mCurrentSourceInfo.mSource->isStreaming(), streamType)
&& (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
// Modular DRM: Disabling audio offload if the source is protected
@@ -1641,9 +1664,9 @@
status_t err = mRenderer->setPlaybackSettings(mPlaybackSettings);
if (err != OK) {
- mSource->stop();
+ mCurrentSourceInfo.mSource->stop();
mSourceStarted = false;
- notifyListener(mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
return;
}
@@ -1665,7 +1688,7 @@
}
startPlaybackTimer("onstart");
- notifyListener(mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
postScanSources();
}
@@ -1691,7 +1714,7 @@
ALOGV("stopPlaybackTimer() log %20" PRId64 "", played);
if (played > 0) {
- driver->notifyMorePlayingTimeUs(mSrcId, (played+500)/1000);
+ driver->notifyMorePlayingTimeUs(mCurrentSourceInfo.mSrcId, (played+500)/1000);
}
}
mLastStartedPlayingTimeNs = 0;
@@ -1709,7 +1732,8 @@
void NuPlayer2::stopRebufferingTimer(bool exitingPlayback) {
Mutex::Autolock autoLock(mPlayingTimeLock);
- ALOGV("stopRebufferTimer() time %20" PRId64 " (exiting %d)", mLastStartedRebufferingTimeNs, exitingPlayback);
+ ALOGV("stopRebufferTimer() time %20" PRId64 " (exiting %d)",
+ mLastStartedRebufferingTimeNs, exitingPlayback);
if (mLastStartedRebufferingTimeNs != 0) {
sp<NuPlayer2Driver> driver = mDriver.promote();
@@ -1719,9 +1743,10 @@
ALOGV("stopRebufferingTimer() log %20" PRId64 "", rebuffered);
if (rebuffered > 0) {
- driver->notifyMoreRebufferingTimeUs(mSrcId, (rebuffered+500)/1000);
+ driver->notifyMoreRebufferingTimeUs(
+ mCurrentSourceInfo.mSrcId, (rebuffered+500)/1000);
if (exitingPlayback) {
- driver->notifyRebufferingWhenExit(mSrcId, true);
+ driver->notifyRebufferingWhenExit(mCurrentSourceInfo.mSrcId, true);
}
}
}
@@ -1737,8 +1762,8 @@
return;
}
mPaused = true;
- if (mSource != NULL) {
- mSource->pause();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ mCurrentSourceInfo.mSource->pause();
} else {
ALOGW("pause called when source is gone or not set");
}
@@ -1828,7 +1853,7 @@
status_t err = mRenderer->openAudioSink(
format, true /* offloadOnly */, hasVideo,
- AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mSource->isStreaming());
+ AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mCurrentSourceInfo.mSource->isStreaming());
if (err != OK) {
// Any failure we turn off mOffloadAudio.
mOffloadAudio = false;
@@ -1881,7 +1906,7 @@
}
void NuPlayer2::determineAudioModeChange(const sp<AMessage> &audioFormat) {
- if (mSource == NULL || mAudioSink == NULL) {
+ if (mCurrentSourceInfo.mSource == NULL || mAudioSink == NULL) {
return;
}
@@ -1891,12 +1916,12 @@
return;
}
- sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
- sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
+ sp<MetaData> audioMeta = mCurrentSourceInfo.mSource->getFormatMeta(true /* audio */);
+ sp<AMessage> videoFormat = mCurrentSourceInfo.mSource->getFormat(false /* audio */);
audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
const bool hasVideo = (videoFormat != NULL);
bool canOffload = canOffloadStream(
- audioMeta, hasVideo, mSource->isStreaming(), streamType)
+ audioMeta, hasVideo, mCurrentSourceInfo.mSource->isStreaming(), streamType)
&& (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
// Modular DRM: Disabling audio offload if the source is protected
@@ -1927,7 +1952,7 @@
return OK;
}
- sp<AMessage> format = mSource->getFormat(audio);
+ sp<AMessage> format = mCurrentSourceInfo.mSource->getFormat(audio);
if (format == NULL) {
return UNKNOWN_ERROR;
@@ -1949,11 +1974,11 @@
mCCDecoder = new CCDecoder(ccNotify);
}
- if (mSourceFlags & Source::FLAG_SECURE) {
+ if (mCurrentSourceInfo.mSourceFlags & Source::FLAG_SECURE) {
format->setInt32("secure", true);
}
- if (mSourceFlags & Source::FLAG_PROTECTED) {
+ if (mCurrentSourceInfo.mSourceFlags & Source::FLAG_PROTECTED) {
format->setInt32("protected", true);
}
@@ -1972,16 +1997,16 @@
determineAudioModeChange(format);
}
if (mOffloadAudio) {
- mSource->setOffloadAudio(true /* offload */);
+ mCurrentSourceInfo.mSource->setOffloadAudio(true /* offload */);
- const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL);
+ const bool hasVideo = (mCurrentSourceInfo.mSource->getFormat(false /*audio */) != NULL);
format->setInt32("has-video", hasVideo);
- *decoder = new DecoderPassThrough(notify, mSource, mRenderer);
+ *decoder = new DecoderPassThrough(notify, mCurrentSourceInfo.mSource, mRenderer);
ALOGV("instantiateDecoder audio DecoderPassThrough hasVideo: %d", hasVideo);
} else {
- mSource->setOffloadAudio(false /* offload */);
+ mCurrentSourceInfo.mSource->setOffloadAudio(false /* offload */);
- *decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer);
+ *decoder = new Decoder(notify, mCurrentSourceInfo.mSource, mPID, mUID, mRenderer);
ALOGV("instantiateDecoder audio Decoder");
}
mAudioDecoderError = false;
@@ -1991,7 +2016,8 @@
notify->setInt32("generation", mVideoDecoderGeneration);
*decoder = new Decoder(
- notify, mSource, mPID, mUID, mRenderer, mNativeWindow, mCCDecoder);
+ notify, mCurrentSourceInfo.mSource, mPID, mUID, mRenderer, mNativeWindow,
+ mCCDecoder);
mVideoDecoderError = false;
// enable FRC if high-quality AV sync is requested, even if not
@@ -2008,8 +2034,8 @@
// Modular DRM
if (mIsDrmProtected) {
format->setObject("crypto", mCrypto);
- ALOGV("instantiateDecoder: mCrypto: %p isSecure: %d", mCrypto.get(),
- (mSourceFlags & Source::FLAG_SECURE) != 0);
+ ALOGV("instantiateDecoder: mCrypto: %p isSecure: %d",
+ mCrypto.get(), (mCurrentSourceInfo.mSourceFlags & Source::FLAG_SECURE) != 0);
}
(*decoder)->configure(format);
@@ -2277,11 +2303,11 @@
}
sp<MetaData> NuPlayer2::getFileMeta() {
- return mSource->getFileFormatMeta();
+ return mCurrentSourceInfo.mSource->getFileFormatMeta();
}
float NuPlayer2::getFrameRate() {
- sp<MetaData> meta = mSource->getFormatMeta(false /* audio */);
+ sp<MetaData> meta = mCurrentSourceInfo.mSource->getFormatMeta(false /* audio */);
if (meta == NULL) {
return 0;
}
@@ -2339,16 +2365,16 @@
ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), mode=%d",
(long long)seekTimeUs, seekTimeUs / 1E6, mode);
- if (mSource == NULL) {
+ if (mCurrentSourceInfo.mSource == NULL) {
// This happens when reset occurs right before the loop mode
// asynchronously seeks to the start of the stream.
LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL,
- "mSource is NULL and decoders not NULL audio(%p) video(%p)",
+ "mCurrentSourceInfo.mSource is NULL and decoders not NULL audio(%p) video(%p)",
mAudioDecoder.get(), mVideoDecoder.get());
return;
}
mPreviousSeekTimeUs = seekTimeUs;
- mSource->seekTo(seekTimeUs, mode);
+ mCurrentSourceInfo.mSource->seekTo(seekTimeUs, mode);
++mTimedTextGeneration;
// everything's flushed, continue playback.
@@ -2395,17 +2421,17 @@
mRenderer.clear();
++mRendererGeneration;
- if (mSource != NULL) {
- mSource->stop();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ mCurrentSourceInfo.mSource->stop();
Mutex::Autolock autoLock(mSourceLock);
- mSource.clear();
+ mCurrentSourceInfo.mSource.clear();
}
if (mDriver != NULL) {
sp<NuPlayer2Driver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifyResetComplete(mSrcId);
+ driver->notifyResetComplete(mCurrentSourceInfo.mSrcId);
}
}
@@ -2440,25 +2466,26 @@
++mRendererGeneration;
- if (mSource != NULL) {
- mSource->stop();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ mCurrentSourceInfo.mSource->stop();
}
long previousSrcId;
{
Mutex::Autolock autoLock(mSourceLock);
- mSource = mNextSource;
- mNextSource = NULL;
- previousSrcId = mSrcId;
- mSrcId = mNextSrcId;
- ++mNextSrcId; // to distinguish the two sources.
+ mCurrentSourceInfo.mSource = mNextSourceInfo.mSource;
+ mNextSourceInfo.mSource = NULL;
+ previousSrcId = mCurrentSourceInfo.mSrcId;
+ mCurrentSourceInfo.mSrcId = mNextSourceInfo.mSrcId;
+ ++mNextSourceInfo.mSrcId; // to distinguish the two sources.
}
if (mDriver != NULL) {
sp<NuPlayer2Driver> driver = mDriver.promote();
if (driver != NULL) {
notifyListener(previousSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_END, 0);
- notifyListener(mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
+ notifyListener(
+ mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
}
}
@@ -2482,7 +2509,7 @@
onStart(true /* play */);
mPausedByClient = false;
- notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_STARTED, 0, 0);
}
void NuPlayer2::performScanSources() {
@@ -2508,7 +2535,7 @@
if (mDriver != NULL) {
sp<NuPlayer2Driver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifySetSurfaceComplete(mSrcId);
+ driver->notifySetSurfaceComplete(mCurrentSourceInfo.mSrcId);
}
}
}
@@ -2540,7 +2567,7 @@
void NuPlayer2::finishResume() {
if (mResumePending) {
mResumePending = false;
- notifyDriverSeekComplete(mSrcId);
+ notifyDriverSeekComplete(mCurrentSourceInfo.mSrcId);
}
}
@@ -2562,8 +2589,9 @@
switch (what) {
case Source::kWhatPrepared:
{
- ALOGV("NuPlayer2::onSourceNotify Source::kWhatPrepared source: %p", mSource.get());
- if (mSource == NULL) {
+ ALOGV("NuPlayer2::onSourceNotify Source::kWhatPrepared source: %p",
+ mCurrentSourceInfo.mSource.get());
+ if (mCurrentSourceInfo.mSource == NULL) {
// This is a stale notification from a source that was
// asynchronously preparing when the client called reset().
// We handled the reset, the source is gone.
@@ -2588,7 +2616,7 @@
// notify duration first, so that it's definitely set when
// the app received the "prepare complete" callback.
int64_t durationUs;
- if (mSource->getDuration(&durationUs) == OK) {
+ if (mCurrentSourceInfo.mSource->getDuration(&durationUs) == OK) {
driver->notifyDuration(srcId, durationUs);
}
driver->notifyPrepareCompleted(srcId, err);
@@ -2640,16 +2668,21 @@
driver->notifyFlagsChanged(srcId, flags);
}
- if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
- && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
- cancelPollDuration();
- } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
- && (flags & Source::FLAG_DYNAMIC_DURATION)
- && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
- schedulePollDuration();
- }
+ if (srcId == mCurrentSourceInfo.mSrcId) {
+ if ((mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
+ && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
+ cancelPollDuration();
+ } else if (!(mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
+ && (flags & Source::FLAG_DYNAMIC_DURATION)
+ && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
+ schedulePollDuration();
+ }
- mSourceFlags = flags;
+ mCurrentSourceInfo.mSourceFlags = flags;
+ } else if (srcId == mNextSourceInfo.mSrcId) {
+ // TODO: handle duration polling for next source.
+ mNextSourceInfo.mSourceFlags = flags;
+ }
break;
}
@@ -2800,8 +2833,8 @@
CHECK(msg->findBuffer("buffer", &buffer));
size_t inbandTracks = 0;
- if (mSource != NULL) {
- inbandTracks = mSource->getTrackCount();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
}
sendSubtitleData(buffer, inbandTracks);
@@ -2810,7 +2843,7 @@
case NuPlayer2::CCDecoder::kWhatTrackAdded:
{
- notifyListener(mSrcId, MEDIA2_INFO, MEDIA2_INFO_METADATA_UPDATE, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_METADATA_UPDATE, 0);
break;
}
@@ -2835,7 +2868,7 @@
playerMsg.add_values()->set_int64_value(durationUs);
playerMsg.add_values()->set_bytes_value(buffer->data(), buffer->size());
- notifyListener(mSrcId, MEDIA2_SUBTITLE_DATA, 0, 0, &playerMsg);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_SUBTITLE_DATA, 0, 0, &playerMsg);
}
void NuPlayer2::sendTimedMetaData(const sp<ABuffer> &buffer) {
@@ -2846,7 +2879,7 @@
playerMsg.add_values()->set_int64_value(timeUs);
playerMsg.add_values()->set_bytes_value(buffer->data(), buffer->size());
- notifyListener(mSrcId, MEDIA2_META_DATA, 0, 0, &playerMsg);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_META_DATA, 0, 0, &playerMsg);
}
void NuPlayer2::sendTimedTextData(const sp<ABuffer> &buffer) {
@@ -2876,14 +2909,14 @@
}
if (playerMsg.values_size() > 0) {
- notifyListener(mSrcId, MEDIA2_TIMED_TEXT, 0, 0, &playerMsg);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_TIMED_TEXT, 0, 0, &playerMsg);
} else { // send an empty timed text
- notifyListener(mSrcId, MEDIA2_TIMED_TEXT, 0, 0);
+ notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_TIMED_TEXT, 0, 0);
}
}
const char *NuPlayer2::getDataSourceType() {
- switch (mDataSourceType) {
+ switch (mCurrentSourceInfo.mDataSourceType) {
case DATA_SOURCE_TYPE_HTTP_LIVE:
return "HTTPLive";
@@ -2957,7 +2990,7 @@
ALOGD("onPrepareDrm ");
status_t status = INVALID_OPERATION;
- if (mSource == NULL) {
+ if (mCurrentSourceInfo.mSource == NULL) {
ALOGE("onPrepareDrm: No source. onPrepareDrm failed with %d.", status);
return status;
}
@@ -2970,12 +3003,12 @@
status = OK;
sp<AMediaCryptoWrapper> crypto = NULL;
- status = mSource->prepareDrm(uuid, *drmSessionId, &crypto);
+ status = mCurrentSourceInfo.mSource->prepareDrm(uuid, *drmSessionId, &crypto);
if (crypto == NULL) {
- ALOGE("onPrepareDrm: mSource->prepareDrm failed. status: %d", status);
+ ALOGE("onPrepareDrm: mCurrentSourceInfo.mSource->prepareDrm failed. status: %d", status);
return status;
}
- ALOGV("onPrepareDrm: mSource->prepareDrm succeeded");
+ ALOGV("onPrepareDrm: mCurrentSourceInfo.mSource->prepareDrm succeeded");
if (mCrypto != NULL) {
ALOGE("onPrepareDrm: Unexpected. Already having mCrypto: %p", mCrypto.get());
@@ -3004,8 +3037,8 @@
status_t status;
if (mCrypto != NULL) {
// notifying the source first before removing crypto from codec
- if (mSource != NULL) {
- mSource->releaseDrm();
+ if (mCurrentSourceInfo.mSource != NULL) {
+ mCurrentSourceInfo.mSource->releaseDrm();
}
status=OK;
@@ -3090,4 +3123,12 @@
TRESPASS();
}
+NuPlayer2::SourceInfo::SourceInfo()
+ : mDataSourceType(DATA_SOURCE_TYPE_NONE),
+ mSrcId(0),
+ mSourceFlags(0),
+ mStartTimeUs(0),
+ mEndTimeUs(INT64_MAX) {
+}
+
} // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index e55cdbe..4db0cbf 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -156,17 +156,33 @@
kWhatReleaseDrm = 'rDrm',
};
+ typedef enum {
+ DATA_SOURCE_TYPE_NONE,
+ DATA_SOURCE_TYPE_HTTP_LIVE,
+ DATA_SOURCE_TYPE_RTSP,
+ DATA_SOURCE_TYPE_GENERIC_URL,
+ DATA_SOURCE_TYPE_GENERIC_FD,
+ DATA_SOURCE_TYPE_MEDIA,
+ } DATA_SOURCE_TYPE;
+
+ struct SourceInfo {
+ SourceInfo();
+
+ sp<Source> mSource;
+ std::atomic<DATA_SOURCE_TYPE> mDataSourceType;
+ int64_t mSrcId;
+ uint32_t mSourceFlags;
+ int64_t mStartTimeUs;
+ int64_t mEndTimeUs;
+ };
+
wp<NuPlayer2Driver> mDriver;
pid_t mPID;
uid_t mUID;
const sp<MediaClock> mMediaClock;
Mutex mSourceLock; // guard |mSource|.
- sp<Source> mSource;
- int64_t mSrcId;
- uint32_t mSourceFlags;
- sp<Source> mNextSource;
- int64_t mNextSrcId;
- uint32_t mNextSourceFlags;
+ SourceInfo mCurrentSourceInfo;
+ SourceInfo mNextSourceInfo;
sp<ANativeWindowWrapper> mNativeWindow;
sp<MediaPlayer2Interface::AudioSink> mAudioSink;
sp<DecoderBase> mVideoDecoder;
@@ -252,18 +268,6 @@
sp<AMediaCryptoWrapper> mCrypto;
bool mIsDrmProtected;
- typedef enum {
- DATA_SOURCE_TYPE_NONE,
- DATA_SOURCE_TYPE_HTTP_LIVE,
- DATA_SOURCE_TYPE_RTSP,
- DATA_SOURCE_TYPE_GENERIC_URL,
- DATA_SOURCE_TYPE_GENERIC_FD,
- DATA_SOURCE_TYPE_MEDIA,
- } DATA_SOURCE_TYPE;
-
- std::atomic<DATA_SOURCE_TYPE> mDataSourceType;
- std::atomic<DATA_SOURCE_TYPE> mNextDataSourceType;
-
inline const sp<DecoderBase> &getDecoder(bool audio) {
return audio ? mAudioDecoder : mVideoDecoder;
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h
index 662235f..9298a99 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h
@@ -69,7 +69,7 @@
BufferingSettings* buffering /* nonnull */) = 0;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) = 0;
- virtual void prepareAsync() = 0;
+ virtual void prepareAsync(int64_t startTimeUs) = 0;
virtual void start() = 0;
virtual void stop() {}
diff --git a/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp b/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
index 1dfe383..53c66c0 100644
--- a/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
@@ -96,7 +96,8 @@
return OK;
}
-void NuPlayer2::RTSPSource2::prepareAsync() {
+// TODO: fetch data starting from |startTimeUs|
+void NuPlayer2::RTSPSource2::prepareAsync(int64_t /* startTimeUs */) {
if (mIsSDP && mHTTPService == NULL) {
notifyPrepared(BAD_VALUE);
return;
diff --git a/media/libmediaplayer2/nuplayer2/RTSPSource2.h b/media/libmediaplayer2/nuplayer2/RTSPSource2.h
index 712c3e5..e5f1716 100644
--- a/media/libmediaplayer2/nuplayer2/RTSPSource2.h
+++ b/media/libmediaplayer2/nuplayer2/RTSPSource2.h
@@ -43,7 +43,7 @@
BufferingSettings* buffering /* nonnull */) override;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
- virtual void prepareAsync();
+ virtual void prepareAsync(int64_t startTimeUs);
virtual void start();
virtual void stop();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b058552..3080db5 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1748,29 +1748,32 @@
}
int32_t storeMeta;
- if (encoder
- && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
- && storeMeta != kMetadataBufferTypeInvalid) {
- IOMX::PortMode mode;
- if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
- mode = IOMX::kPortModeDynamicNativeHandle;
- } else if (storeMeta == kMetadataBufferTypeANWBuffer ||
- storeMeta == kMetadataBufferTypeGrallocSource) {
- mode = IOMX::kPortModeDynamicANWBuffer;
- } else {
- return BAD_VALUE;
+ if (encoder) {
+ IOMX::PortMode mode = IOMX::kPortModePresetByteBuffer;
+ if (msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
+ && storeMeta != kMetadataBufferTypeInvalid) {
+ if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
+ mode = IOMX::kPortModeDynamicNativeHandle;
+ } else if (storeMeta == kMetadataBufferTypeANWBuffer ||
+ storeMeta == kMetadataBufferTypeGrallocSource) {
+ mode = IOMX::kPortModeDynamicANWBuffer;
+ } else {
+ return BAD_VALUE;
+ }
}
err = setPortMode(kPortIndexInput, mode);
if (err != OK) {
return err;
}
- uint32_t usageBits;
- if (mOMXNode->getParameter(
- (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
- &usageBits, sizeof(usageBits)) == OK) {
- inputFormat->setInt32(
- "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
+ if (mode != IOMX::kPortModePresetByteBuffer) {
+ uint32_t usageBits;
+ if (mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &usageBits, sizeof(usageBits)) == OK) {
+ inputFormat->setInt32(
+ "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
+ }
}
}
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/libstagefright/MetaDataUtils.cpp
index 5672145..2cf79c3 100644
--- a/media/libstagefright/MetaDataUtils.cpp
+++ b/media/libstagefright/MetaDataUtils.cpp
@@ -19,8 +19,10 @@
#include <utils/Log.h>
#include <media/stagefright/foundation/avc_utils.h>
+#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataUtils.h>
#include <media/stagefright/Utils.h>
@@ -192,4 +194,135 @@
return true;
}
+
+static void extractAlbumArt(
+ AMediaFormat *fileMeta, const void *data, size_t size) {
+ ALOGV("extractAlbumArt from '%s'", (const char *)data);
+
+ size_t inLen = strnlen((const char *)data, size);
+ size_t flacSize = inLen / 4 * 3;
+ uint8_t *flac = new uint8_t[flacSize];
+ if (!decodeBase64(flac, &flacSize, (const char*)data)) {
+ ALOGE("malformed base64 encoded data.");
+ delete[] flac;
+ return;
+ }
+
+ ALOGV("got flac of size %zu", flacSize);
+
+ uint32_t picType;
+ uint32_t typeLen;
+ uint32_t descLen;
+ uint32_t dataLen;
+ char type[128];
+
+ if (flacSize < 8) {
+ delete[] flac;
+ return;
+ }
+
+ picType = U32_AT(flac);
+
+ if (picType != 3) {
+ // This is not a front cover.
+ delete[] flac;
+ return;
+ }
+
+ typeLen = U32_AT(&flac[4]);
+ if (typeLen > sizeof(type) - 1) {
+ delete[] flac;
+ return;
+ }
+
+ // we've already checked above that flacSize >= 8
+ if (flacSize - 8 < typeLen) {
+ delete[] flac;
+ return;
+ }
+
+ memcpy(type, &flac[8], typeLen);
+ type[typeLen] = '\0';
+
+ ALOGV("picType = %d, type = '%s'", picType, type);
+
+ if (!strcmp(type, "-->")) {
+ // This is not inline cover art, but an external url instead.
+ delete[] flac;
+ return;
+ }
+
+ if (flacSize < 32 || flacSize - 32 < typeLen) {
+ delete[] flac;
+ return;
+ }
+
+ descLen = U32_AT(&flac[8 + typeLen]);
+ if (flacSize - 32 - typeLen < descLen) {
+ delete[] flac;
+ return;
+ }
+
+ dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
+
+ // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
+ if (flacSize - 32 - typeLen - descLen < dataLen) {
+ delete[] flac;
+ return;
+ }
+
+ ALOGV("got image data, %zu trailing bytes",
+ flacSize - 32 - typeLen - descLen - dataLen);
+
+ AMediaFormat_setBuffer(fileMeta, AMEDIAFORMAT_KEY_ALBUMART,
+ &flac[8 + typeLen + 4 + descLen + 20], dataLen);
+
+ delete[] flac;
+}
+
+void parseVorbisComment(
+ AMediaFormat *fileMeta, const char *comment, size_t commentLength) {
+ struct {
+ const char *const mTag;
+ const char *mKey;
+ } kMap[] = {
+ { "TITLE", AMEDIAFORMAT_KEY_TITLE },
+ { "ARTIST", AMEDIAFORMAT_KEY_ARTIST },
+ { "ALBUMARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST },
+ { "ALBUM ARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST },
+ { "COMPILATION", AMEDIAFORMAT_KEY_COMPILATION },
+ { "ALBUM", AMEDIAFORMAT_KEY_ALBUM },
+ { "COMPOSER", AMEDIAFORMAT_KEY_COMPOSER },
+ { "GENRE", AMEDIAFORMAT_KEY_GENRE },
+ { "AUTHOR", AMEDIAFORMAT_KEY_AUTHOR },
+ { "TRACKNUMBER", AMEDIAFORMAT_KEY_CDTRACKNUMBER },
+ { "DISCNUMBER", AMEDIAFORMAT_KEY_DISCNUMBER },
+ { "DATE", AMEDIAFORMAT_KEY_DATE },
+ { "YEAR", AMEDIAFORMAT_KEY_YEAR },
+ { "LYRICIST", AMEDIAFORMAT_KEY_LYRICIST },
+ { "METADATA_BLOCK_PICTURE", AMEDIAFORMAT_KEY_ALBUMART },
+ { "ANDROID_LOOP", AMEDIAFORMAT_KEY_LOOP },
+ };
+
+ for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
+ size_t tagLen = strlen(kMap[j].mTag);
+ if (!strncasecmp(kMap[j].mTag, comment, tagLen)
+ && comment[tagLen] == '=') {
+ if (kMap[j].mKey == AMEDIAFORMAT_KEY_ALBUMART) {
+ extractAlbumArt(
+ fileMeta,
+ &comment[tagLen + 1],
+ commentLength - tagLen - 1);
+ } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_LOOP) {
+ if (!strcasecmp(&comment[tagLen + 1], "true")) {
+ AMediaFormat_setInt32(fileMeta, AMEDIAFORMAT_KEY_LOOP, 1);
+ }
+ } else {
+ AMediaFormat_setString(fileMeta, kMap[j].mKey, &comment[tagLen + 1]);
+ }
+ }
+ }
+
+}
+
} // namespace android
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index ebc3b33..456e2e3 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -569,6 +569,62 @@
}
+std::vector<std::pair<const char *, uint32_t>> tagMappings {
+ {
+ { "album", kKeyAlbum },
+ { "albumartist", kKeyAlbumArtist },
+ { "artist", kKeyArtist },
+ { "author", kKeyAuthor },
+ { "cdtracknum", kKeyCDTrackNumber },
+ { "compilation", kKeyCompilation },
+ { "composer", kKeyComposer },
+ { "date", kKeyDate },
+ { "discnum", kKeyDiscNumber },
+ { "genre", kKeyGenre },
+ { "lyricist", kKeyWriter },
+ { "title", kKeyTitle },
+ { "year", kKeyYear },
+ }
+};
+
+void convertMessageToMetaDataTags(const sp<AMessage> &msg, sp<MetaData> &meta) {
+ for (auto elem : tagMappings) {
+ AString value;
+ if (msg->findString(elem.first, &value)) {
+ meta->setCString(elem.second, value.c_str());
+ }
+ }
+ sp<ABuffer> buf;
+ if (msg->findBuffer("albumart", &buf)) {
+ meta->setData(kKeyAlbumArt, MetaDataBase::Type::TYPE_NONE, buf->data(), buf->size());
+ }
+
+ int32_t loop;
+ if (msg->findInt32("loop", &loop)) {
+ meta->setInt32(kKeyAutoLoop, loop);
+ }
+}
+
+void convertMetaDataToMessageTags(const MetaDataBase *meta, sp<AMessage> format) {
+ for (auto elem : tagMappings) {
+ const char *value;
+ if (meta->findCString(elem.second, &value)) {
+ format->setString(elem.first, value, strlen(value));
+ }
+ }
+ uint32_t type;
+ const void* data;
+ size_t size;
+ if (meta->findData(kKeyAlbumArt, &type, &data, &size)) {
+ sp<ABuffer> buf = ABuffer::CreateAsCopy(data, size);
+ format->setBuffer("albumart", buf);
+ }
+ int32_t loop;
+ if (meta->findInt32(kKeyAutoLoop, &loop)) {
+ format->setInt32("loop", loop);
+ }
+}
+
status_t convertMetaDataToMessage(
const sp<MetaData> &meta, sp<AMessage> *format) {
return convertMetaDataToMessage(meta.get(), format);
@@ -592,6 +648,8 @@
sp<AMessage> msg = new AMessage;
msg->setString("mime", mime);
+ convertMetaDataToMessageTags(meta, msg);
+
uint32_t type;
const void *data;
size_t size;
@@ -1298,6 +1356,8 @@
ALOGW("did not find mime type");
}
+ convertMessageToMetaDataTags(msg, meta);
+
int64_t durationUs;
if (msg->findInt64("durationUs", &durationUs)) {
meta->setInt64(kKeyDuration, durationUs);
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 6d93807..8c1da76 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -1106,6 +1106,14 @@
consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
mConsumer->setConsumerUsageBits(consumerUsage);
+ // Set impl. defined format as default. Depending on the usage flags
+ // the device-specific implementation will derive the exact format.
+ err = mConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+ if (err != NO_ERROR) {
+ ALOGE("Failed to configure surface default format ret: %d", err);
+ return err;
+ }
+
// Sets the default buffer data space
ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
diff --git a/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp b/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp
index 4868822..36a7393 100644
--- a/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp
+++ b/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp
@@ -234,6 +234,7 @@
dec_6p_6N_2(L_index, 4, 0, pos);
add_pulses(pos, 6, k, code);
}
+ break;
default:
break;
}
diff --git a/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp b/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp
index 0325311..4d1126e 100644
--- a/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp
+++ b/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp
@@ -170,6 +170,7 @@
case 0x38000000:
case 0x30000000:
i++;
+ break;
default:
;
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp
index e579bbd..885ab08 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp
@@ -160,6 +160,7 @@
case 0x38000000:
case 0x30000000:
i++;
+ break;
default:
;
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
index 8f32582..834b88f 100644
--- a/media/libstagefright/foundation/base64.cpp
+++ b/media/libstagefright/foundation/base64.cpp
@@ -28,14 +28,31 @@
return NULL;
}
+ size_t bufSize = n / 4 * 3;
+ sp<ABuffer> buf = new ABuffer(bufSize);
+
+ if (decodeBase64(buf->data(), &bufSize, s.c_str())) {
+ buf->setRange(0, bufSize);
+ return buf;
+ }
+ return NULL;
+}
+
+bool decodeBase64(uint8_t *out, size_t *inOutBufSize, const char* s) {
+ size_t n = strlen(s);
+
+ if ((n % 4) != 0) {
+ return false;
+ }
+
size_t padding = 0;
- if (n >= 1 && s.c_str()[n - 1] == '=') {
+ if (n >= 1 && s[n - 1] == '=') {
padding = 1;
- if (n >= 2 && s.c_str()[n - 2] == '=') {
+ if (n >= 2 && s[n - 2] == '=') {
padding = 2;
- if (n >= 3 && s.c_str()[n - 3] == '=') {
+ if (n >= 3 && s[n - 3] == '=') {
padding = 3;
}
}
@@ -45,15 +62,13 @@
// already made sure that n % 4 == 0.
size_t outLen = (n / 4) * 3 - padding;
- sp<ABuffer> buffer = new ABuffer(outLen);
- uint8_t *out = buffer->data();
- if (out == NULL || buffer->size() < outLen) {
- return NULL;
+ if (out == NULL || *inOutBufSize < outLen) {
+ return false;
}
size_t j = 0;
uint32_t accum = 0;
for (size_t i = 0; i < n; ++i) {
- char c = s.c_str()[i];
+ char c = s[i];
unsigned value;
if (c >= 'A' && c <= 'Z') {
value = c - 'A';
@@ -66,10 +81,10 @@
} else if (c == '/' || c == '_') {
value = 63;
} else if (c != '=') {
- return NULL;
+ return false;
} else {
if (i < n - padding) {
- return NULL;
+ return false;
}
value = 0;
@@ -86,7 +101,8 @@
}
}
- return buffer;
+ *inOutBufSize = j;
+ return true;
}
static char encode6Bit(unsigned x) {
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h b/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
index abc95e0..60fb9ff 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
@@ -26,6 +26,9 @@
struct AString;
sp<ABuffer> decodeBase64(const AString &s);
+
+bool decodeBase64(uint8_t *out, size_t *inOutBufSize, const char* s);
+
void encodeBase64(const void *data, size_t size, AString *out);
void encodeBase64Url(const void *data, size_t size, AString *out);
diff --git a/media/libstagefright/include/media/stagefright/MetaDataUtils.h b/media/libstagefright/include/media/stagefright/MetaDataUtils.h
index fd79a9e..e87c7f9 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataUtils.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataUtils.h
@@ -34,6 +34,9 @@
bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index,
unsigned channel_configuration);
+void parseVorbisComment(
+ AMediaFormat *fileMeta, const char *comment, size_t commentLength);
+
} // namespace android
#endif // META_DATA_UTILS_H_
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 99762b9..68b375a 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -536,6 +536,9 @@
}
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
if (cmd == OMX_CommandStateSet) {
// There are no configurations past first StateSet command.
@@ -600,6 +603,9 @@
status_t OMXNodeInstance::getParameter(
OMX_INDEXTYPE index, void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
if (isProhibitedIndex_l(index)) {
android_errorWriteLog(0x534e4554, "29422020");
@@ -618,6 +624,10 @@
status_t OMXNodeInstance::setParameter(
OMX_INDEXTYPE index, const void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
+
OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
@@ -639,6 +649,9 @@
status_t OMXNodeInstance::getConfig(
OMX_INDEXTYPE index, void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
if (isProhibitedIndex_l(index)) {
android_errorWriteLog(0x534e4554, "29422020");
@@ -657,6 +670,10 @@
status_t OMXNodeInstance::setConfig(
OMX_INDEXTYPE index, const void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
+
OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
@@ -673,6 +690,9 @@
status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
if (portIndex >= NELEM(mPortMode)) {
ALOGE("b/31385713, portIndex(%u)", portIndex);
@@ -855,6 +875,9 @@
status_t OMXNodeInstance::getGraphicBufferUsage(
OMX_U32 portIndex, OMX_U32* usage) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
@@ -968,6 +991,10 @@
OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
OMX_U32 maxFrameHeight) {
Mutex::Autolock autolock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
+
if (mSailed) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
@@ -1008,6 +1035,10 @@
OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
native_handle_t **sidebandHandle) {
Mutex::Autolock autolock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
+
if (mSailed) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
@@ -1062,6 +1093,10 @@
}
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
+
if (!mSailed) {
ALOGE("b/35467458");
android_errorWriteLog(0x534e4554, "35467458");
@@ -1478,6 +1513,9 @@
status_t OMXNodeInstance::setInputSurface(
const sp<IOMXBufferSource> &bufferSource) {
Mutex::Autolock autolock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
status_t err;
@@ -1544,6 +1582,9 @@
}
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
if (!mSailed) {
ALOGE("b/35467458");
@@ -1600,6 +1641,10 @@
status_t OMXNodeInstance::freeBuffer(
OMX_U32 portIndex, IOMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
+
CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer);
removeActiveBuffer(portIndex, buffer);
@@ -1627,6 +1672,9 @@
status_t OMXNodeInstance::fillBuffer(
IOMX::buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
if (header == NULL) {
@@ -1677,6 +1725,9 @@
buffer_id buffer, const OMXBuffer &omxBuffer,
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
switch (omxBuffer.mBufferType) {
case OMXBuffer::kBufferTypePreset:
@@ -1991,6 +2042,9 @@
status_t OMXNodeInstance::getExtensionIndex(
const char *parameterName, OMX_INDEXTYPE *index) {
Mutex::Autolock autoLock(mLock);
+ if (mHandle == NULL) {
+ return DEAD_OBJECT;
+ }
OMX_ERRORTYPE err = OMX_GetExtensionIndex(
mHandle, const_cast<char *>(parameterName), index);
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 0667df1..49e01c0 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -400,8 +400,10 @@
switch (count) {
case 3:
data[offset++] = 0;
+ [[fallthrough]];
case 2:
data[offset++] = 0;
+ [[fallthrough]];
case 1:
data[offset++] = 0;
}
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index 43c89bb..3c10024 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -224,6 +224,11 @@
}
sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+ if (source == NULL) {
+ ALOGE("AMediaDataSource_newUri source is null");
+ return NULL;
+ }
+ ALOGI("AMediaDataSource_newUri source %s flags %u", source->toString().c_str(), source->flags());
AMediaDataSource* aSource = convertDataSourceToAMediaDataSource(source);
aSource->mImpl = source;
aSource->mFlags = source->flags();
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 503f726..22fbb42 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -268,27 +268,40 @@
EXPORT const char* AMEDIAFORMAT_KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT = "aac-max-output-channel_count";
EXPORT const char* AMEDIAFORMAT_KEY_AAC_PROFILE = "aac-profile";
EXPORT const char* AMEDIAFORMAT_KEY_AAC_SBR_MODE = "aac-sbr-mode";
+EXPORT const char* AMEDIAFORMAT_KEY_ALBUM = "album";
+EXPORT const char* AMEDIAFORMAT_KEY_ALBUMART = "albumart";
+EXPORT const char* AMEDIAFORMAT_KEY_ALBUMARTIST = "albumartist";
+EXPORT const char* AMEDIAFORMAT_KEY_ARTIST = "artist";
EXPORT const char* AMEDIAFORMAT_KEY_AUDIO_SESSION_ID = "audio-session-id";
+EXPORT const char* AMEDIAFORMAT_KEY_AUTHOR = "author";
EXPORT const char* AMEDIAFORMAT_KEY_BITRATE_MODE = "bitrate-mode";
EXPORT const char* AMEDIAFORMAT_KEY_BIT_RATE = "bitrate";
EXPORT const char* AMEDIAFORMAT_KEY_CAPTURE_RATE = "capture-rate";
+EXPORT const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER = "cdtracknum";
EXPORT const char* AMEDIAFORMAT_KEY_CHANNEL_COUNT = "channel-count";
EXPORT const char* AMEDIAFORMAT_KEY_CHANNEL_MASK = "channel-mask";
EXPORT const char* AMEDIAFORMAT_KEY_COLOR_FORMAT = "color-format";
EXPORT const char* AMEDIAFORMAT_KEY_COLOR_RANGE = "color-range";
EXPORT const char* AMEDIAFORMAT_KEY_COLOR_STANDARD = "color-standard";
EXPORT const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER = "color-transfer";
+EXPORT const char* AMEDIAFORMAT_KEY_COMPILATION = "compilation";
EXPORT const char* AMEDIAFORMAT_KEY_COMPLEXITY = "complexity";
+EXPORT const char* AMEDIAFORMAT_KEY_COMPOSER = "composer";
EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_2 = "csd-2";
+EXPORT const char* AMEDIAFORMAT_KEY_DATE = "date";
+EXPORT const char* AMEDIAFORMAT_KEY_DISCNUMBER = "discnum";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_HEIGHT = "display-height";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_WIDTH = "display-width";
EXPORT const char* AMEDIAFORMAT_KEY_DURATION = "durationUs";
+EXPORT const char* AMEDIAFORMAT_KEY_ENCODER_DELAY = "encoder-delay";
+EXPORT const char* AMEDIAFORMAT_KEY_ENCODER_PADDING = "encoder-padding";
EXPORT const char* AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
EXPORT const char* AMEDIAFORMAT_KEY_FRAME_RATE = "frame-rate";
+EXPORT const char* AMEDIAFORMAT_KEY_GENRE = "genre";
EXPORT const char* AMEDIAFORMAT_KEY_GRID_COLUMNS = "grid-cols";
EXPORT const char* AMEDIAFORMAT_KEY_GRID_ROWS = "grid-rows";
EXPORT const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO = "hdr-static-info";
@@ -302,6 +315,8 @@
EXPORT const char* AMEDIAFORMAT_KEY_LANGUAGE = "language";
EXPORT const char* AMEDIAFORMAT_KEY_LATENCY = "latency";
EXPORT const char* AMEDIAFORMAT_KEY_LEVEL = "level";
+EXPORT const char* AMEDIAFORMAT_KEY_LOOP = "loop";
+EXPORT const char* AMEDIAFORMAT_KEY_LYRICIST = "lyricist";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_HEIGHT = "max-height";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";
@@ -323,9 +338,11 @@
EXPORT const char* AMEDIAFORMAT_KEY_TILE_HEIGHT = "tile-height";
EXPORT const char* AMEDIAFORMAT_KEY_TILE_WIDTH = "tile-width";
EXPORT const char* AMEDIAFORMAT_KEY_TIME_US = "timeUs";
+EXPORT const char* AMEDIAFORMAT_KEY_TITLE = "title";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
+EXPORT const char* AMEDIAFORMAT_KEY_YEAR = "year";
} // extern "C"
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 3f853d0..3fc28f3 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -86,10 +86,6 @@
void AMediaFormat_setBuffer(AMediaFormat*, const char* name, const void* data, size_t size) __INTRODUCED_IN(21);
-
-/**
- * XXX should these be ints/enums that we look up in a table as needed?
- */
extern const char* AMEDIAFORMAT_KEY_AAC_DRC_ATTENUATION_FACTOR __INTRODUCED_IN(28);
extern const char* AMEDIAFORMAT_KEY_AAC_DRC_BOOST_FACTOR __INTRODUCED_IN(28);
extern const char* AMEDIAFORMAT_KEY_AAC_DRC_HEAVY_COMPRESSION __INTRODUCED_IN(28);
@@ -156,7 +152,6 @@
extern const char* AMEDIAFORMAT_KEY_TRACK_ID __INTRODUCED_IN(28);
extern const char* AMEDIAFORMAT_KEY_TRACK_INDEX __INTRODUCED_IN(28);
extern const char* AMEDIAFORMAT_KEY_WIDTH __INTRODUCED_IN(21);
-
#endif /* __ANDROID_API__ >= 21 */
#if __ANDROID_API__ >= 28
@@ -180,6 +175,25 @@
* copy one AMediaFormat to another
*/
media_status_t AMediaFormat_copy(AMediaFormat *to, AMediaFormat *from) __INTRODUCED_IN(29);
+
+extern const char* AMEDIAFORMAT_KEY_ALBUM __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ALBUMART __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ALBUMARTIST __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ARTIST __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_AUTHOR __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_COMPILATION __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_DATE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_DISCNUMBER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ENCODER_DELAY __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ENCODER_PADDING __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_LOOP __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_LYRICIST __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_TITLE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);
+
#endif /* __ANDROID_API__ >= 29 */
__END_DECLS
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index 7f16289..802f86f 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -35,7 +35,6 @@
import android.media.MediaPlayer2;
import android.media.MediaPlayer2.EventCallback;
import android.media.MediaPlayer2Impl;
-import android.media.Metadata;
import android.media.PlaybackParams;
import android.media.SessionToken2;
import android.media.SubtitleData;
@@ -125,7 +124,7 @@
private MediaControlView2 mMediaControlView;
private MediaSession mMediaSession;
private MediaController mMediaController;
- private Metadata mMetadata;
+ private boolean mSeekable;
private MediaMetadata2 mMediaMetadata;
private MediaMetadataRetriever mRetriever;
private boolean mNeedUpdateMediaType;
@@ -262,6 +261,7 @@
mSpeed = 1.0f;
mFallbackSpeed = mSpeed;
mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
+ mSeekable = true;
// TODO: add attributes to get this value.
mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
@@ -795,33 +795,11 @@
private void updatePlaybackState() {
if (mStateBuilder == null) {
- // Get the capabilities of the player for this stream
- mMetadata = mMediaPlayer.getMetadata(MediaPlayer2.METADATA_ALL,
- MediaPlayer2.BYPASS_METADATA_FILTER);
-
// Add Play action as default
- long playbackActions = PlaybackState.ACTION_PLAY;
- if (mMetadata != null) {
- if (!mMetadata.has(Metadata.PAUSE_AVAILABLE)
- || mMetadata.getBoolean(Metadata.PAUSE_AVAILABLE)) {
- playbackActions |= PlaybackState.ACTION_PAUSE;
- }
- if (!mMetadata.has(Metadata.SEEK_BACKWARD_AVAILABLE)
- || mMetadata.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE)) {
- playbackActions |= PlaybackState.ACTION_REWIND;
- }
- if (!mMetadata.has(Metadata.SEEK_FORWARD_AVAILABLE)
- || mMetadata.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE)) {
- playbackActions |= PlaybackState.ACTION_FAST_FORWARD;
- }
- if (!mMetadata.has(Metadata.SEEK_AVAILABLE)
- || mMetadata.getBoolean(Metadata.SEEK_AVAILABLE)) {
- playbackActions |= PlaybackState.ACTION_SEEK_TO;
- }
- } else {
- playbackActions |= (PlaybackState.ACTION_PAUSE |
- PlaybackState.ACTION_REWIND | PlaybackState.ACTION_FAST_FORWARD |
- PlaybackState.ACTION_SEEK_TO);
+ long playbackActions = PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE;
+ if (mSeekable) {
+ playbackActions |= (PlaybackState.ACTION_REWIND |
+ PlaybackState.ACTION_FAST_FORWARD | PlaybackState.ACTION_SEEK_TO);
}
mStateBuilder = new PlaybackState.Builder();
mStateBuilder.setActions(playbackActions);
@@ -1004,9 +982,6 @@
private void extractMetadata() {
// Get and set duration and title values as MediaMetadata for MediaControlView2
MediaMetadata.Builder builder = new MediaMetadata.Builder();
- if (mMetadata != null && mMetadata.has(Metadata.TITLE)) {
- mTitle = mMetadata.getString(Metadata.TITLE);
- }
builder.putString(MediaMetadata.METADATA_KEY_TITLE, mTitle);
builder.putLong(
MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration());
@@ -1169,6 +1144,8 @@
this.onCompletion(mp, dsd);
} else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
this.onBufferingUpdate(mp, dsd, extra);
+ } else if (what == MediaPlayer2.MEDIA_INFO_NOT_SEEKABLE) {
+ mSeekable = false;
}
}
@@ -1180,6 +1157,7 @@
}
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
+ mSeekable = true;
updatePlaybackState();
if (mMediaControlView != null) {
@@ -1254,6 +1232,7 @@
private void onCompletion(MediaPlayer2 mp, DataSourceDesc dsd) {
mCurrentState = STATE_PLAYBACK_COMPLETED;
mTargetState = STATE_PLAYBACK_COMPLETED;
+ mSeekable = true;
updatePlaybackState();
if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
mAudioManager.abandonAudioFocus(null);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 01c5ea2..52a8fa8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6654,6 +6654,7 @@
case TrackBase::PAUSING:
mActiveTracks.remove(activeTrack);
+ activeTrack->mState = TrackBase::PAUSED;
doBroadcast = true;
size--;
continue;
@@ -6675,12 +6676,12 @@
allStopped = false;
break;
- case TrackBase::IDLE:
- i++;
- continue;
-
+ case TrackBase::IDLE: // cannot be on ActiveTracks if idle
+ case TrackBase::PAUSED: // cannot be on ActiveTracks if paused
+ case TrackBase::STOPPED: // cannot be on ActiveTracks if destroyed/terminated
default:
- LOG_ALWAYS_FATAL("Unexpected activeTrackState %d", activeTrackState);
+ LOG_ALWAYS_FATAL("%s: Unexpected active track state:%d, id:%d, tracks:%zu",
+ __func__, activeTrackState, activeTrack->id(), size);
}
activeTracks.add(activeTrack);
@@ -7323,8 +7324,14 @@
{
// This section is a rendezvous between binder thread executing start() and RecordThread
AutoMutex lock(mLock);
+ if (recordTrack->isInvalid()) {
+ recordTrack->clearSyncStartEvent();
+ return INVALID_OPERATION;
+ }
if (mActiveTracks.indexOf(recordTrack) >= 0) {
if (recordTrack->mState == TrackBase::PAUSING) {
+ // We haven't stopped yet (moved to PAUSED and not in mActiveTracks)
+ // so no need to startInput().
ALOGV("active record track PAUSING -> ACTIVE");
recordTrack->mState = TrackBase::ACTIVE;
} else {
@@ -7344,11 +7351,30 @@
bool silenced;
status = AudioSystem::startInput(recordTrack->portId(), &silenced);
mLock.lock();
- // FIXME should verify that recordTrack is still in mActiveTracks
+ if (recordTrack->isInvalid()) {
+ recordTrack->clearSyncStartEvent();
+ if (status == NO_ERROR && recordTrack->mState == TrackBase::STARTING_1) {
+ recordTrack->mState = TrackBase::STARTING_2;
+ // STARTING_2 forces destroy to call stopInput.
+ }
+ return INVALID_OPERATION;
+ }
+ if (recordTrack->mState != TrackBase::STARTING_1) {
+ ALOGW("%s(%d): unsynchronized mState:%d change",
+ __func__, recordTrack->id(), recordTrack->mState);
+ // Someone else has changed state, let them take over,
+ // leave mState in the new state.
+ recordTrack->clearSyncStartEvent();
+ return INVALID_OPERATION;
+ }
+ // we're ok, but perhaps startInput has failed
if (status != NO_ERROR) {
+ ALOGW("%s(%d): startInput failed, status %d",
+ __func__, recordTrack->id(), status);
+ // We are in ActiveTracks if STARTING_1 and valid, so remove from ActiveTracks,
+ // leave in STARTING_1, so destroy() will not call stopInput.
mActiveTracks.remove(recordTrack);
recordTrack->clearSyncStartEvent();
- ALOGV("RecordThread::start error %d", status);
return status;
}
recordTrack->setSilenced(silenced);
@@ -7366,21 +7392,8 @@
recordTrack->mState = TrackBase::STARTING_2;
// signal thread to start
mWaitWorkCV.broadcast();
- if (mActiveTracks.indexOf(recordTrack) < 0) {
- ALOGV("Record failed to start");
- status = BAD_VALUE;
- goto startError;
- }
return status;
}
-
-startError:
- if (recordTrack->isExternalTrack()) {
- AudioSystem::stopInput(recordTrack->portId());
- }
- recordTrack->clearSyncStartEvent();
- // FIXME I wonder why we do not reset the state here?
- return status;
}
void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
@@ -7399,24 +7412,26 @@
bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
ALOGV("RecordThread::stop");
AutoMutex _l(mLock);
+ // if we're invalid, we can't be on the ActiveTracks.
if (mActiveTracks.indexOf(recordTrack) < 0 || recordTrack->mState == TrackBase::PAUSING) {
return false;
}
// note that threadLoop may still be processing the track at this point [without lock]
recordTrack->mState = TrackBase::PAUSING;
- // signal thread to stop
- mWaitWorkCV.broadcast();
- // do not wait for mStartStopCond if exiting
- if (exitPending()) {
- return true;
+
+ while (recordTrack->mState == TrackBase::PAUSING && !recordTrack->isInvalid()) {
+ mWaitWorkCV.broadcast(); // signal thread to stop
+ mStartStopCond.wait(mLock);
}
- // FIXME incorrect usage of wait: no explicit predicate or loop
- mStartStopCond.wait(mLock);
- // if we have been restarted, recordTrack is in mActiveTracks here
- if (exitPending() || mActiveTracks.indexOf(recordTrack) < 0) {
+
+ if (recordTrack->mState == TrackBase::PAUSED) { // successful stop
ALOGV("Record stopped OK");
return true;
}
+
+ // don't handle anything - we've been invalidated or restarted and in a different state
+ ALOGW_IF("%s(%d): unsynchronized stop, state: %d",
+ __func__, recordTrack->id(), recordTrack->mState);
return false;
}
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 92e79f2..c94639b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -25,13 +25,13 @@
public:
enum track_state {
IDLE,
- FLUSHED,
+ FLUSHED, // for PlaybackTracks only
STOPPED,
// next 2 states are currently used for fast tracks
// and offloaded tracks only
STOPPING_1, // waiting for first underrun
STOPPING_2, // waiting for presentation complete
- RESUMING,
+ RESUMING, // for PlaybackTracks only
ACTIVE,
PAUSING,
PAUSED,
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a99bbe1..f2617ae 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1823,17 +1823,34 @@
// see comments at AudioFlinger::PlaybackThread::Track::destroy()
sp<RecordTrack> keep(this);
{
- if (isExternalTrack()) {
- if (mState == ACTIVE || mState == RESUMING) {
- AudioSystem::stopInput(mPortId);
- }
- AudioSystem::releaseInput(mPortId);
- }
+ track_state priorState = mState;
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
RecordThread *recordThread = (RecordThread *) thread.get();
- recordThread->destroyTrack_l(this);
+ priorState = mState;
+ recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
+ }
+ // APM portid/client management done outside of lock.
+ // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
+ if (isExternalTrack()) {
+ switch (priorState) {
+ case ACTIVE: // invalidated while still active
+ case STARTING_2: // invalidated/start-aborted after startInput successfully called
+ case PAUSING: // invalidated while in the middle of stop() pausing (still active)
+ AudioSystem::stopInput(mPortId);
+ break;
+
+ case STARTING_1: // invalidated/start-aborted and startInput not successful
+ case PAUSED: // OK, not active
+ case IDLE: // OK, not active
+ break;
+
+ case STOPPED: // unexpected (destroyed)
+ default:
+ LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
+ }
+ AudioSystem::releaseInput(mPortId);
}
}
}
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index f42cdd3..97f7fdc 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -551,9 +551,11 @@
return DONE;
}
- if (l.mParameters.isDeviceZslSupported) {
+ if ((l.mParameters.isDeviceZslSupported) && (l.mParameters.state != Parameters::RECORD) &&
+ (l.mParameters.state != Parameters::VIDEO_SNAPSHOT)) {
// If device ZSL is supported, drop all pending preview buffers to reduce the chance of
// rendering preview frames newer than the still frame.
+ // Additionally, preview must not get interrupted during video recording.
client->getCameraDevice()->dropStreamBuffers(true, client->getPreviewStreamId());
}
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 314ff01..789548d 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -72,7 +72,27 @@
LOCAL_REQUIRED_MODULES_arm := crash_dump.policy mediacodec.policy
LOCAL_REQUIRED_MODULES_x86 := crash_dump.policy mediacodec.policy
endif
-LOCAL_SRC_FILES := main_swcodecservice.cpp
+LOCAL_SRC_FILES := \
+ main_swcodecservice.cpp \
+ MediaCodecUpdateService.cpp \
+
+sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
+ $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+ $(UBSAN_RUNTIME_LIBRARY) \
+ $(TSAN_RUNTIME_LIBRARY) \
+ $(2ND_ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+ $(2ND_UBSAN_RUNTIME_LIBRARY) \
+ $(2ND_TSAN_RUNTIME_LIBRARY)))
+
+# $(info Sanitizer: $(sanitizer_runtime_libraries))
+
+llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\
+ $(LLNDK_LIBRARIES)))
+
+# $(info LLNDK: $(llndk_libraries))
+
+LOCAL_CFLAGS := -DLINKED_LIBRARIES='"$(sanitizer_runtime_libraries):$(llndk_libraries)"'
+
LOCAL_SHARED_LIBRARIES := \
libavservices_minijail \
libbase \
@@ -89,6 +109,9 @@
LOCAL_INIT_RC := mediaswcodec.rc
LOCAL_32_BIT_ONLY := true
+sanitizer_runtime_libraries :=
+llndk_libraries :=
+
include $(BUILD_EXECUTABLE)
####################################################################
diff --git a/services/mediacodec/MediaCodecUpdateService.cpp b/services/mediacodec/MediaCodecUpdateService.cpp
new file mode 100644
index 0000000..a2bb469
--- /dev/null
+++ b/services/mediacodec/MediaCodecUpdateService.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MediaCodecUpdateService"
+//#define LOG_NDEBUG 0
+
+#include <android/dlext.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <media/CodecServiceRegistrant.h>
+#include <utils/Log.h>
+#include <ziparchive/zip_archive.h>
+#include <cutils/properties.h>
+
+#include "MediaCodecUpdateService.h"
+
+// Copied from GraphicsEnv.cpp
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+ android_namespace_t* android_create_namespace(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ android_namespace_t* parent);
+ bool android_link_namespaces(android_namespace_t* from,
+ android_namespace_t* to,
+ const char* shared_libs_sonames);
+ enum {
+ ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+ };
+}
+
+namespace android {
+namespace media {
+
+binder::Status MediaCodecUpdateService::loadPlugins(const ::std::string& apkPath) {
+ ALOGV("loadPlugins %s", apkPath.c_str());
+
+ ZipArchiveHandle zipHandle;
+ void *registrantLib = NULL;
+ int32_t ret = OpenArchive(apkPath.c_str(), &zipHandle);
+
+ if (ret == 0) {
+ char abilist32[PROPERTY_VALUE_MAX];
+ property_get("ro.product.cpu.abilist32", abilist32, "armeabi-v7a");
+
+ auto abis = base::Split(abilist32, ",");
+ if (abis.empty()) {
+ ALOGW("abilist is empty, trying armeabi-v7a ...");
+ abis.push_back("armeabi-v7a");
+ }
+
+ // TODO: Only try the first entry in abilist32 for now.
+ // We probably should try the next if it fails.
+ String8 libPathInApk = String8("lib/") + String8(abis[0].c_str());
+ String8 defaultLibPath = String8(apkPath.c_str()) + "!/" + libPathInApk;
+ String8 libPath = defaultLibPath + "/libmedia_codecserviceregistrant.so";
+
+ ZipEntry entry;
+ ZipString name(libPathInApk + "/libmedia_codecserviceregistrant.so");
+ ret = FindEntry(zipHandle, name, &entry);
+
+ if (ret == 0) {
+ android_namespace_t *codecNs = android_create_namespace("codecs",
+ nullptr, // ld_library_path
+ defaultLibPath.c_str(),
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr); // parent
+
+ if (codecNs != nullptr) {
+ String8 linked_libraries(LINKED_LIBRARIES);
+ if (android_link_namespaces(
+ codecNs, nullptr, linked_libraries.c_str())) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = codecNs,
+ };
+
+ registrantLib = android_dlopen_ext(
+ libPath.string(),
+ RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+
+ if (registrantLib == NULL) {
+ ALOGE("Failed to load lib from archive: %s", dlerror());
+ }
+ } else {
+ ALOGE("Failed to link namespace");
+ }
+ } else {
+ ALOGE("Failed to create codec namespace");
+ }
+ } else {
+ ALOGE("Failed to find entry (ret=%d)", ret);
+ }
+
+ CloseArchive(zipHandle);
+ } else {
+ ALOGE("Failed to open archive (ret=%d)", ret);
+ }
+
+ if (registrantLib) {
+ RegisterCodecServicesFunc registerCodecServices =
+ reinterpret_cast<RegisterCodecServicesFunc>(
+ dlsym(registrantLib, "RegisterCodecServices"));
+ if (registerCodecServices) {
+ registerCodecServices();
+ } else {
+ LOG(WARNING) << "Cannot register codec services "
+ "-- corrupted library.";
+ }
+ } else {
+ LOG(ERROR) << "Cannot find codec service registrant.";
+ }
+
+ return binder::Status::ok();
+}
+
+} // namespace media
+} // namespace android
diff --git a/services/mediacodec/MediaCodecUpdateService.h b/services/mediacodec/MediaCodecUpdateService.h
new file mode 100644
index 0000000..7b7cee9
--- /dev/null
+++ b/services/mediacodec/MediaCodecUpdateService.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
+#define ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
+
+#include <binder/BinderService.h>
+#include <android/media/BnMediaUpdateService.h>
+
+namespace android {
+namespace media {
+
+class MediaCodecUpdateService
+ : public BinderService<MediaCodecUpdateService>, public BnMediaUpdateService
+{
+ friend class BinderService<MediaCodecUpdateService>;
+public:
+ MediaCodecUpdateService() : BnMediaUpdateService() { }
+ virtual ~MediaCodecUpdateService() { }
+ static const char* getServiceName() { return "media.codec.update"; }
+ binder::Status loadPlugins(const ::std::string& apkPath);
+};
+
+} // namespace media
+} // namespace android
+
+#endif // ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index 1729c3f..386abb2 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -20,10 +20,13 @@
// from LOCAL_C_INCLUDES
#include "minijail.h"
+#include <android-base/properties.h>
#include <binder/ProcessState.h>
+#include <dlfcn.h>
#include <hidl/HidlTransportSupport.h>
#include <media/CodecServiceRegistrant.h>
-#include <dlfcn.h>
+
+#include "MediaCodecUpdateService.h"
using namespace android;
@@ -40,6 +43,11 @@
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
+ std::string value = base::GetProperty("ro.build.type", "unknown");
+ if (value == "userdebug" || value == "eng") {
+ media::MediaCodecUpdateService::instantiate();
+ }
+
android::ProcessState::self()->startThreadPool();
::android::hardware::configureRpcThreadpool(64, false);
diff --git a/services/mediaextractor/MediaExtractorUpdateService.h b/services/mediaextractor/MediaExtractorUpdateService.h
index 4115f6d..ea34c9d 100644
--- a/services/mediaextractor/MediaExtractorUpdateService.h
+++ b/services/mediaextractor/MediaExtractorUpdateService.h
@@ -18,17 +18,17 @@
#define ANDROID_MEDIA_EXTRACTOR_UPDATE_SERVICE_H
#include <binder/BinderService.h>
-#include <android/media/BnMediaExtractorUpdateService.h>
+#include <android/media/BnMediaUpdateService.h>
namespace android {
namespace media {
class MediaExtractorUpdateService
- : public BinderService<MediaExtractorUpdateService>, public BnMediaExtractorUpdateService
+ : public BinderService<MediaExtractorUpdateService>, public BnMediaUpdateService
{
friend class BinderService<MediaExtractorUpdateService>;
public:
- MediaExtractorUpdateService() : BnMediaExtractorUpdateService() { }
+ MediaExtractorUpdateService() : BnMediaUpdateService() { }
virtual ~MediaExtractorUpdateService() { }
static const char* getServiceName() { return "media.extractor.update"; }
binder::Status loadPlugins(const ::std::string& apkPath);