Merge "Convert clearkey plugin to HIDL"
diff --git a/include/media/DataSourceBase.h b/include/media/DataSourceBase.h
new file mode 120000
index 0000000..54c8047
--- /dev/null
+++ b/include/media/DataSourceBase.h
@@ -0,0 +1 @@
+../../media/libmediaextractor/include/media/DataSourceBase.h
\ No newline at end of file
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
index b0199d4..2287aca 100644
--- a/include/media/MicrophoneInfo.h
+++ b/include/media/MicrophoneInfo.h
@@ -42,7 +42,7 @@
MicrophoneInfo(audio_microphone_characteristic_t& characteristic) {
mDeviceId = String16(&characteristic.device_id[0]);
mPortId = characteristic.id;
- mType = characteristic.type;
+ mType = characteristic.device;
mAddress = String16(&characteristic.address[0]);
mDeviceLocation = characteristic.location;
mDeviceGroup = characteristic.group;
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 6f28374..1614ca4 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -19,7 +19,7 @@
#include <utils/Log.h>
#include "AACExtractor.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -35,7 +35,7 @@
class AACSource : public MediaSourceBase {
public:
- AACSource(const sp<DataSource> &source,
+ AACSource(DataSourceBase *source,
const sp<MetaData> &meta,
const Vector<uint64_t> &offset_vector,
int64_t frame_duration_us);
@@ -53,7 +53,7 @@
private:
static const size_t kMaxFrameSize;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mMeta;
off64_t mOffset;
@@ -91,7 +91,7 @@
// The returned value is the AAC frame size with the ADTS header length (regardless of
// the presence of the CRC).
// If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame.
-static size_t getAdtsFrameLength(const sp<DataSource> &source, off64_t offset, size_t* headerSize) {
+static size_t getAdtsFrameLength(DataSourceBase *source, off64_t offset, size_t* headerSize) {
const size_t kAdtsHeaderLengthNoCrc = 7;
const size_t kAdtsHeaderLengthWithCrc = 9;
@@ -132,7 +132,7 @@
}
AACExtractor::AACExtractor(
- const sp<DataSource> &source, const sp<AMessage> &_meta)
+ DataSourceBase *source, const sp<AMessage> &_meta)
: mDataSource(source),
mInitCheck(NO_INIT),
mFrameDurationUs(0) {
@@ -229,7 +229,7 @@
const size_t AACSource::kMaxFrameSize = 8192;
AACSource::AACSource(
- const sp<DataSource> &source, const sp<MetaData> &meta,
+ DataSourceBase *source, const sp<MetaData> &meta,
const Vector<uint64_t> &offset_vector,
int64_t frame_duration_us)
: mDataSource(source),
@@ -332,13 +332,13 @@
////////////////////////////////////////////////////////////////////////////////
static MediaExtractor* CreateExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta) {
return new AACExtractor(source, meta);
}
static MediaExtractor::CreatorFunc Sniff(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *meta) {
off64_t pos = 0;
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index 33fbba7..e99699c 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -29,7 +29,7 @@
class AACExtractor : public MediaExtractor {
public:
- AACExtractor(const sp<DataSource> &source, const sp<AMessage> &meta);
+ AACExtractor(DataSourceBase *source, const sp<AMessage> &meta);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +42,7 @@
virtual ~AACExtractor();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mMeta;
status_t mInitCheck;
@@ -54,7 +54,7 @@
};
bool SniffAAC(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 10be50c..547e3f5 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -20,7 +20,7 @@
#include "AMRExtractor.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -33,7 +33,7 @@
class AMRSource : public MediaSourceBase {
public:
- AMRSource(const sp<DataSource> &source,
+ AMRSource(DataSourceBase *source,
const sp<MetaData> &meta,
bool isWide,
const off64_t *offset_table,
@@ -51,7 +51,7 @@
virtual ~AMRSource();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mMeta;
bool mIsWide;
@@ -97,7 +97,7 @@
return frameSize;
}
-static status_t getFrameSizeByOffset(const sp<DataSource> &source,
+static status_t getFrameSizeByOffset(DataSourceBase *source,
off64_t offset, bool isWide, size_t *frameSize) {
uint8_t header;
ssize_t count = source->readAt(offset, &header, 1);
@@ -116,7 +116,7 @@
return OK;
}
-AMRExtractor::AMRExtractor(const sp<DataSource> &source)
+AMRExtractor::AMRExtractor(DataSourceBase *source)
: mDataSource(source),
mInitCheck(NO_INIT),
mOffsetTableLength(0) {
@@ -206,7 +206,7 @@
////////////////////////////////////////////////////////////////////////////////
AMRSource::AMRSource(
- const sp<DataSource> &source, const sp<MetaData> &meta,
+ DataSourceBase *source, const sp<MetaData> &meta,
bool isWide, const off64_t *offset_table, size_t offset_table_length)
: mDataSource(source),
mMeta(meta),
@@ -339,7 +339,7 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffAMR(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
char header[9];
@@ -372,13 +372,13 @@
1,
"AMR Extractor",
[](
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
if (SniffAMR(source, mimeType, confidence, meta)) {
return [](
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) -> MediaExtractor* {
return new AMRExtractor(source);};
}
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index 56883e3..d6d49f2 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -29,7 +29,7 @@
class AMRExtractor : public MediaExtractor {
public:
- explicit AMRExtractor(const sp<DataSource> &source);
+ explicit AMRExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +42,7 @@
virtual ~AMRExtractor();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mMeta;
status_t mInitCheck;
bool mIsWide;
@@ -55,7 +55,7 @@
};
bool SniffAMR(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index ba28e86..8dbb5a1 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -22,7 +22,7 @@
// libFLAC parser
#include "FLAC/stream_decoder.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -165,7 +165,7 @@
public:
FLACSource(
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
const sp<MetaData> &trackMetadata);
virtual status_t start(MetaData *params);
@@ -179,7 +179,7 @@
virtual ~FLACSource();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mTrackMetadata;
sp<FLACParser> mParser;
bool mInitCheck;
@@ -203,7 +203,7 @@
};
explicit FLACParser(
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
// If metadata pointers aren't provided, we don't fill them
const sp<MetaData> &fileMetadata = 0,
const sp<MetaData> &trackMetadata = 0);
@@ -243,7 +243,7 @@
virtual ~FLACParser();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mFileMetadata;
sp<MetaData> mTrackMetadata;
bool mInitCheck;
@@ -612,7 +612,7 @@
// FLACParser
FLACParser::FLACParser(
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
const sp<MetaData> &fileMetadata,
const sp<MetaData> &trackMetadata)
: mDataSource(dataSource),
@@ -833,7 +833,7 @@
// FLACsource
FLACSource::FLACSource(
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
const sp<MetaData> &trackMetadata)
: mDataSource(dataSource),
mTrackMetadata(trackMetadata),
@@ -918,7 +918,7 @@
// FLACExtractor
FLACExtractor::FLACExtractor(
- const sp<DataSource> &dataSource)
+ DataSourceBase *dataSource)
: mDataSource(dataSource),
mInitCheck(false)
{
@@ -969,7 +969,7 @@
// Sniffer
bool SniffFLAC(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *)
{
// first 4 is the signature word
@@ -1000,13 +1000,13 @@
1,
"FLAC Extractor",
[](
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
if (SniffFLAC(source, mimeType, confidence, meta)) {
return [](
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) -> MediaExtractor* {
return new FLACExtractor(source);};
}
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 2e7ee3b..ef07212 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -17,7 +17,7 @@
#ifndef FLAC_EXTRACTOR_H_
#define FLAC_EXTRACTOR_H_
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaExtractor.h>
#include <utils/String8.h>
@@ -28,8 +28,7 @@
class FLACExtractor : public MediaExtractor {
public:
- // Extractor assumes ownership of source
- explicit FLACExtractor(const sp<DataSource> &source);
+ explicit FLACExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +41,7 @@
virtual ~FLACExtractor();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<FLACParser> mParser;
status_t mInitCheck;
sp<MetaData> mFileMetadata;
@@ -57,7 +56,7 @@
};
-bool SniffFLAC(const sp<DataSource> &source, String8 *mimeType,
+bool SniffFLAC(DataSourceBase *source, String8 *mimeType,
float *confidence, sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 18b1d23..711c6a5 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -141,7 +141,7 @@
// MidiEngine
-MidiEngine::MidiEngine(const sp<DataSource> &dataSource,
+MidiEngine::MidiEngine(DataSourceBase *dataSource,
const sp<MetaData> &fileMetadata,
const sp<MetaData> &trackMetadata) :
mGroup(NULL),
@@ -261,7 +261,7 @@
// MidiExtractor
MidiExtractor::MidiExtractor(
- const sp<DataSource> &dataSource)
+ DataSourceBase *dataSource)
: mDataSource(dataSource),
mInitCheck(false)
{
@@ -308,7 +308,7 @@
// Sniffer
bool SniffMidi(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *)
{
sp<MidiEngine> p = new MidiEngine(source, NULL, NULL);
@@ -333,13 +333,13 @@
1,
"MIDI Extractor",
[](
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
if (SniffMidi(source, mimeType, confidence, meta)) {
return [](
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) -> MediaExtractor* {
return new MidiExtractor(source);};
}
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 87e4654..91efd06 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -17,7 +17,7 @@
#ifndef MIDI_EXTRACTOR_H_
#define MIDI_EXTRACTOR_H_
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaExtractor.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -29,7 +29,7 @@
class MidiEngine : public RefBase {
public:
- MidiEngine(const sp<DataSource> &dataSource,
+ MidiEngine(DataSourceBase *dataSource,
const sp<MetaData> &fileMetadata,
const sp<MetaData> &trackMetadata);
~MidiEngine();
@@ -52,8 +52,7 @@
class MidiExtractor : public MediaExtractor {
public:
- // Extractor assumes ownership of source
- explicit MidiExtractor(const sp<DataSource> &source);
+ explicit MidiExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -66,7 +65,7 @@
virtual ~MidiExtractor();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
status_t mInitCheck;
sp<MetaData> mFileMetadata;
@@ -88,7 +87,7 @@
};
-bool SniffMidi(const sp<DataSource> &source, String8 *mimeType,
+bool SniffMidi(DataSourceBase *source, String8 *mimeType,
float *confidence, sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 6df0012..f61f7c7 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -21,7 +21,7 @@
#include "FLACDecoder.h"
#include "MatroskaExtractor.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -40,8 +40,8 @@
namespace android {
-struct DataSourceReader : public mkvparser::IMkvReader {
- explicit DataSourceReader(const sp<DataSource> &source)
+struct DataSourceBaseReader : public mkvparser::IMkvReader {
+ explicit DataSourceBaseReader(DataSourceBase *source)
: mSource(source) {
}
@@ -83,10 +83,10 @@
}
private:
- sp<DataSource> mSource;
+ DataSourceBase *mSource;
- DataSourceReader(const DataSourceReader &);
- DataSourceReader &operator=(const DataSourceReader &);
+ DataSourceBaseReader(const DataSourceBaseReader &);
+ DataSourceBaseReader &operator=(const DataSourceBaseReader &);
};
////////////////////////////////////////////////////////////////////////////////
@@ -852,9 +852,9 @@
////////////////////////////////////////////////////////////////////////////////
-MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
+MatroskaExtractor::MatroskaExtractor(DataSourceBase *source)
: mDataSource(source),
- mReader(new DataSourceReader(mDataSource)),
+ mReader(new DataSourceBaseReader(mDataSource)),
mSegment(NULL),
mExtractedThumbnails(false),
mIsWebm(false),
@@ -862,8 +862,8 @@
off64_t size;
mIsLiveStreaming =
(mDataSource->flags()
- & (DataSource::kWantsPrefetching
- | DataSource::kIsCachingDataSource))
+ & (DataSourceBase::kWantsPrefetching
+ | DataSourceBase::kIsCachingDataSource))
&& mDataSource->getSize(&size) != OK;
mkvparser::EBMLHeader ebmlHeader;
@@ -1548,9 +1548,9 @@
}
bool SniffMatroska(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
- DataSourceReader reader(source);
+ DataSourceBaseReader reader(source);
mkvparser::EBMLHeader ebmlHeader;
long long pos;
if (ebmlHeader.Parse(&reader, pos) < 0) {
@@ -1574,13 +1574,13 @@
1,
"Matroska Extractor",
[](
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
if (SniffMatroska(source, mimeType, confidence, meta)) {
return [](
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) -> MediaExtractor* {
return new MatroskaExtractor(source);};
}
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 54419bf..095452b 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -30,11 +30,11 @@
class String8;
class MetaData;
-struct DataSourceReader;
+struct DataSourceBaseReader;
struct MatroskaSource;
struct MatroskaExtractor : public MediaExtractor {
- explicit MatroskaExtractor(const sp<DataSource> &source);
+ explicit MatroskaExtractor(DataSourceBase *source);
virtual size_t countTracks();
@@ -76,8 +76,8 @@
Mutex mLock;
Vector<TrackInfo> mTracks;
- sp<DataSource> mDataSource;
- DataSourceReader *mReader;
+ DataSourceBase *mDataSource;
+ DataSourceBaseReader *mReader;
mkvparser::Segment *mSegment;
bool mExtractedThumbnails;
bool mIsLiveStreaming;
@@ -96,7 +96,7 @@
};
bool SniffMatroska(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 7e27fd8..25d4deb 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -24,7 +24,7 @@
#include "VBRISeeker.h"
#include "XINGSeeker.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -46,7 +46,7 @@
static const uint32_t kMask = 0xfffe0c00;
static bool Resync(
- const sp<DataSource> &source, uint32_t match_header,
+ DataSourceBase *source, uint32_t match_header,
off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) {
if (post_id3_pos != NULL) {
*post_id3_pos = 0;
@@ -212,7 +212,7 @@
class MP3Source : public MediaSourceBase {
public:
MP3Source(
- const sp<MetaData> &meta, const sp<DataSource> &source,
+ const sp<MetaData> &meta, DataSourceBase *source,
off64_t first_frame_pos, uint32_t fixed_header,
const sp<MP3Seeker> &seeker);
@@ -230,7 +230,7 @@
private:
static const size_t kMaxFrameSize;
sp<MetaData> mMeta;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
off64_t mFirstFramePos;
uint32_t mFixedHeader;
off64_t mCurrentPos;
@@ -247,7 +247,7 @@
};
MP3Extractor::MP3Extractor(
- const sp<DataSource> &source, const sp<AMessage> &meta)
+ DataSourceBase *source, const sp<AMessage> &meta)
: mInitCheck(NO_INIT),
mDataSource(source),
mFirstFramePos(-1),
@@ -436,7 +436,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(
- const sp<MetaData> &meta, const sp<DataSource> &source,
+ const sp<MetaData> &meta, DataSourceBase *source,
off64_t first_frame_pos, uint32_t fixed_header,
const sp<MP3Seeker> &seeker)
: mMeta(meta),
@@ -667,13 +667,13 @@
}
static MediaExtractor* CreateExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta) {
return new MP3Extractor(source, meta);
}
static MediaExtractor::CreatorFunc Sniff(
- const sp<DataSource> &source, String8 *mimeType,
+ DataSourceBase *source, String8 *mimeType,
float *confidence, sp<AMessage> *meta) {
off64_t pos = 0;
off64_t post_id3_pos;
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 3b3387d..6257112 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -24,14 +24,13 @@
namespace android {
struct AMessage;
-class DataSource;
+class DataSourceBase;
struct MP3Seeker;
class String8;
class MP3Extractor : public MediaExtractor {
public:
- // Extractor assumes ownership of "source".
- MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
+ MP3Extractor(DataSourceBase *source, const sp<AMessage> &meta);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -43,7 +42,7 @@
private:
status_t mInitCheck;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
off64_t mFirstFramePos;
sp<MetaData> mMeta;
uint32_t mFixedHeader;
@@ -54,7 +53,7 @@
};
bool SniffMP3(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *meta);
} // namespace android
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index e7db6fd..51c5d1f 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -27,7 +27,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ByteUtils.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
namespace android {
@@ -37,7 +37,7 @@
// static
sp<VBRISeeker> VBRISeeker::CreateFromSource(
- const sp<DataSource> &source, off64_t post_id3_pos) {
+ DataSourceBase *source, off64_t post_id3_pos) {
off64_t pos = post_id3_pos;
uint8_t header[4];
diff --git a/media/extractors/mp3/VBRISeeker.h b/media/extractors/mp3/VBRISeeker.h
index 87258b0..e46af36 100644
--- a/media/extractors/mp3/VBRISeeker.h
+++ b/media/extractors/mp3/VBRISeeker.h
@@ -24,11 +24,11 @@
namespace android {
-class DataSource;
+class DataSourceBase;
struct VBRISeeker : public MP3Seeker {
static sp<VBRISeeker> CreateFromSource(
- const sp<DataSource> &source, off64_t post_id3_pos);
+ DataSourceBase *source, off64_t post_id3_pos);
virtual bool getDuration(int64_t *durationUs);
virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/extractors/mp3/XINGSeeker.cpp
index fa59701..adfa8d2 100644
--- a/media/extractors/mp3/XINGSeeker.cpp
+++ b/media/extractors/mp3/XINGSeeker.cpp
@@ -21,7 +21,7 @@
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/ByteUtils.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
namespace android {
@@ -77,7 +77,7 @@
// static
sp<XINGSeeker> XINGSeeker::CreateFromSource(
- const sp<DataSource> &source, off64_t first_frame_pos) {
+ DataSourceBase *source, off64_t first_frame_pos) {
sp<XINGSeeker> seeker = new XINGSeeker;
seeker->mFirstFramePos = first_frame_pos;
diff --git a/media/extractors/mp3/XINGSeeker.h b/media/extractors/mp3/XINGSeeker.h
index 37077c4..db847bc 100644
--- a/media/extractors/mp3/XINGSeeker.h
+++ b/media/extractors/mp3/XINGSeeker.h
@@ -22,11 +22,11 @@
namespace android {
-class DataSource;
+class DataSourceBase;
struct XINGSeeker : public MP3Seeker {
static sp<XINGSeeker> CreateFromSource(
- const sp<DataSource> &source, off64_t first_frame_pos);
+ DataSourceBase *source, off64_t first_frame_pos);
virtual bool getDuration(int64_t *durationUs);
virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index 85c66b2..cef5f4a 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "ItemTable"
#include <ItemTable.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -87,7 +87,7 @@
struct Box {
protected:
- Box(const sp<DataSource> source, uint32_t type) :
+ Box(DataSourceBase *source, uint32_t type) :
mDataSource(source), mType(type) {}
virtual ~Box() {}
@@ -99,14 +99,14 @@
inline uint32_t type() const { return mType; }
- inline sp<DataSource> source() const { return mDataSource; }
+ inline DataSourceBase *source() const { return mDataSource; }
status_t parseChunk(off64_t *offset);
status_t parseChunks(off64_t offset, size_t size);
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
uint32_t mType;
};
@@ -181,7 +181,7 @@
struct FullBox : public Box {
protected:
- FullBox(const sp<DataSource> source, uint32_t type) :
+ FullBox(DataSourceBase *source, uint32_t type) :
Box(source, type), mVersion(0), mFlags(0) {}
inline uint8_t version() const { return mVersion; }
@@ -216,7 +216,7 @@
//
struct PitmBox : public FullBox {
- PitmBox(const sp<DataSource> source) :
+ PitmBox(DataSourceBase *source) :
FullBox(source, FOURCC('p', 'i', 't', 'm')) {}
status_t parse(off64_t offset, size_t size, uint32_t *primaryItemId);
@@ -296,7 +296,7 @@
};
struct IlocBox : public FullBox {
- IlocBox(const sp<DataSource> source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
+ IlocBox(DataSourceBase *source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
FullBox(source, FOURCC('i', 'l', 'o', 'c')),
mItemLocs(itemLocs), mHasConstructMethod1(false) {}
@@ -466,7 +466,7 @@
//
struct ItemReference : public Box, public RefBase {
- ItemReference(const sp<DataSource> source, uint32_t type, uint32_t itemIdSize) :
+ ItemReference(DataSourceBase *source, uint32_t type, uint32_t itemIdSize) :
Box(source, type), mItemId(0), mRefIdSize(itemIdSize) {}
status_t parse(off64_t offset, size_t size);
@@ -575,7 +575,7 @@
}
struct IrefBox : public FullBox {
- IrefBox(const sp<DataSource> source, Vector<sp<ItemReference> > *itemRefs) :
+ IrefBox(DataSourceBase *source, Vector<sp<ItemReference> > *itemRefs) :
FullBox(source, FOURCC('i', 'r', 'e', 'f')), mRefIdSize(0), mItemRefs(itemRefs) {}
status_t parse(off64_t offset, size_t size);
@@ -637,7 +637,7 @@
};
struct IspeBox : public FullBox, public ItemProperty {
- IspeBox(const sp<DataSource> source) :
+ IspeBox(DataSourceBase *source) :
FullBox(source, FOURCC('i', 's', 'p', 'e')), mWidth(0), mHeight(0) {}
status_t parse(off64_t offset, size_t size) override;
@@ -673,7 +673,7 @@
}
struct HvccBox : public Box, public ItemProperty {
- HvccBox(const sp<DataSource> source) :
+ HvccBox(DataSourceBase *source) :
Box(source, FOURCC('h', 'v', 'c', 'C')) {}
status_t parse(off64_t offset, size_t size) override;
@@ -706,7 +706,7 @@
}
struct IrotBox : public Box, public ItemProperty {
- IrotBox(const sp<DataSource> source) :
+ IrotBox(DataSourceBase *source) :
Box(source, FOURCC('i', 'r', 'o', 't')), mAngle(0) {}
status_t parse(off64_t offset, size_t size) override;
@@ -735,7 +735,7 @@
}
struct ColrBox : public Box, public ItemProperty {
- ColrBox(const sp<DataSource> source) :
+ ColrBox(DataSourceBase *source) :
Box(source, FOURCC('c', 'o', 'l', 'r')) {}
status_t parse(off64_t offset, size_t size) override;
@@ -783,7 +783,7 @@
}
struct IpmaBox : public FullBox {
- IpmaBox(const sp<DataSource> source, Vector<AssociationEntry> *associations) :
+ IpmaBox(DataSourceBase *source, Vector<AssociationEntry> *associations) :
FullBox(source, FOURCC('i', 'p', 'm', 'a')), mAssociations(associations) {}
status_t parse(off64_t offset, size_t size);
@@ -857,7 +857,7 @@
}
struct IpcoBox : public Box {
- IpcoBox(const sp<DataSource> source, Vector<sp<ItemProperty> > *properties) :
+ IpcoBox(DataSourceBase *source, Vector<sp<ItemProperty> > *properties) :
Box(source, FOURCC('i', 'p', 'c', 'o')), mItemProperties(properties) {}
status_t parse(off64_t offset, size_t size);
@@ -914,7 +914,7 @@
}
struct IprpBox : public Box {
- IprpBox(const sp<DataSource> source,
+ IprpBox(DataSourceBase *source,
Vector<sp<ItemProperty> > *properties,
Vector<AssociationEntry> *associations) :
Box(source, FOURCC('i', 'p', 'r', 'p')),
@@ -971,7 +971,7 @@
};
struct InfeBox : public FullBox {
- InfeBox(const sp<DataSource> source) :
+ InfeBox(DataSourceBase *source) :
FullBox(source, FOURCC('i', 'n', 'f', 'e')) {}
status_t parse(off64_t offset, size_t size, ItemInfo *itemInfo);
@@ -1075,7 +1075,7 @@
}
struct IinfBox : public FullBox {
- IinfBox(const sp<DataSource> source, Vector<ItemInfo> *itemInfos) :
+ IinfBox(DataSourceBase *source, Vector<ItemInfo> *itemInfos) :
FullBox(source, FOURCC('i', 'i', 'n', 'f')),
mItemInfos(itemInfos), mHasGrids(false) {}
@@ -1144,7 +1144,7 @@
//////////////////////////////////////////////////////////////////
-ItemTable::ItemTable(const sp<DataSource> &source)
+ItemTable::ItemTable(DataSourceBase *source)
: mDataSource(source),
mPrimaryItemId(0),
mIdatOffset(0),
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index 3d2e2ae..f4a69cc 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -25,7 +25,7 @@
namespace android {
-class DataSource;
+class DataSourceBase;
class MetaData;
namespace heif {
@@ -44,7 +44,7 @@
class ItemTable : public RefBase {
public:
- explicit ItemTable(const sp<DataSource> &source);
+ explicit ItemTable(DataSourceBase *source);
status_t parse(uint32_t type, off64_t offset, size_t size);
@@ -60,7 +60,7 @@
~ItemTable();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
KeyedVector<uint32_t, ItemLoc> mItemLocs;
Vector<ItemInfo> mItemInfos;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 9f21db6..30dda13 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -69,7 +69,7 @@
public:
// Caller retains ownership of both "dataSource" and "sampleTable".
MPEG4Source(const sp<MetaData> &format,
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
int32_t timeScale,
const sp<SampleTable> &sampleTable,
Vector<SidxEntry> &sidx,
@@ -93,7 +93,7 @@
Mutex mLock;
sp<MetaData> mFormat;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
int32_t mTimescale;
sp<SampleTable> mSampleTable;
uint32_t mCurrentSampleIndex;
@@ -186,47 +186,51 @@
// all remaining requests to the wrapped datasource.
// This is used to cache the full sampletable metadata for a single track,
// possibly wrapping multiple times to cover all tracks, i.e.
-// Each MPEG4DataSource caches the sampletable metadata for a single track.
+// Each CachedRangedDataSource caches the sampletable metadata for a single track.
-struct MPEG4DataSource : public DataSource {
- explicit MPEG4DataSource(const sp<DataSource> &source);
+struct CachedRangedDataSource : public DataSourceBase {
+ explicit CachedRangedDataSource(DataSourceBase *source);
+ virtual ~CachedRangedDataSource();
virtual status_t initCheck() const;
virtual ssize_t readAt(off64_t offset, void *data, size_t size);
virtual status_t getSize(off64_t *size);
virtual uint32_t flags();
- status_t setCachedRange(off64_t offset, size_t size);
+ status_t setCachedRange(off64_t offset, size_t size, bool assumeSourceOwnershipOnSuccess);
-protected:
- virtual ~MPEG4DataSource();
private:
Mutex mLock;
- sp<DataSource> mSource;
+ DataSourceBase *mSource;
+ bool mOwnsDataSource;
off64_t mCachedOffset;
size_t mCachedSize;
uint8_t *mCache;
void clearCache();
- MPEG4DataSource(const MPEG4DataSource &);
- MPEG4DataSource &operator=(const MPEG4DataSource &);
+ CachedRangedDataSource(const CachedRangedDataSource &);
+ CachedRangedDataSource &operator=(const CachedRangedDataSource &);
};
-MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
+CachedRangedDataSource::CachedRangedDataSource(DataSourceBase *source)
: mSource(source),
+ mOwnsDataSource(false),
mCachedOffset(0),
mCachedSize(0),
mCache(NULL) {
}
-MPEG4DataSource::~MPEG4DataSource() {
+CachedRangedDataSource::~CachedRangedDataSource() {
clearCache();
+ if (mOwnsDataSource) {
+ delete (CachedRangedDataSource*)mSource;
+ }
}
-void MPEG4DataSource::clearCache() {
+void CachedRangedDataSource::clearCache() {
if (mCache) {
free(mCache);
mCache = NULL;
@@ -236,11 +240,11 @@
mCachedSize = 0;
}
-status_t MPEG4DataSource::initCheck() const {
+status_t CachedRangedDataSource::initCheck() const {
return mSource->initCheck();
}
-ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
+ssize_t CachedRangedDataSource::readAt(off64_t offset, void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
@@ -251,15 +255,17 @@
return mSource->readAt(offset, data, size);
}
-status_t MPEG4DataSource::getSize(off64_t *size) {
+status_t CachedRangedDataSource::getSize(off64_t *size) {
return mSource->getSize(size);
}
-uint32_t MPEG4DataSource::flags() {
+uint32_t CachedRangedDataSource::flags() {
return mSource->flags();
}
-status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
+status_t CachedRangedDataSource::setCachedRange(off64_t offset,
+ size_t size,
+ bool assumeSourceOwnershipOnSuccess) {
Mutex::Autolock autoLock(mLock);
clearCache();
@@ -280,7 +286,7 @@
return ERROR_IO;
}
-
+ mOwnsDataSource = assumeSourceOwnershipOnSuccess;
return OK;
}
@@ -334,11 +340,12 @@
return false;
}
-MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source, const char *mime)
+MPEG4Extractor::MPEG4Extractor(DataSourceBase *source, const char *mime)
: mMoofOffset(0),
mMoofFound(false),
mMdatFound(false),
mDataSource(source),
+ mCachedSource(NULL),
mInitCheck(NO_INIT),
mHeaderTimescale(0),
mIsQT(false),
@@ -354,10 +361,6 @@
}
MPEG4Extractor::~MPEG4Extractor() {
- release();
-}
-
-void MPEG4Extractor::release() {
Track *track = mFirstTrack;
while (track) {
Track *next = track->next;
@@ -381,10 +384,7 @@
}
mPssh.clear();
- if (mDataSource != NULL) {
- mDataSource->close();
- mDataSource.clear();
- }
+ delete mCachedSource;
}
uint32_t MPEG4Extractor::flags() const {
@@ -692,14 +692,14 @@
// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
static int32_t readSize(off64_t offset,
- const sp<DataSource> &DataSource, uint8_t *numOfBytes) {
+ DataSourceBase *DataSourceBase, uint8_t *numOfBytes) {
uint32_t size = 0;
uint8_t data;
bool moreData = true;
*numOfBytes = 0;
while (moreData) {
- if (DataSource->readAt(offset, &data, 1) < 1) {
+ if (DataSourceBase->readAt(offset, &data, 1) < 1) {
return -1;
}
offset ++;
@@ -1045,13 +1045,17 @@
ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
if (mDataSource->flags()
- & (DataSource::kWantsPrefetching
- | DataSource::kIsCachingDataSource)) {
- sp<MPEG4DataSource> cachedSource =
- new MPEG4DataSource(mDataSource);
+ & (DataSourceBase::kWantsPrefetching
+ | DataSourceBase::kIsCachingDataSource)) {
+ CachedRangedDataSource *cachedSource =
+ new CachedRangedDataSource(mDataSource);
- if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
- mDataSource = cachedSource;
+ if (cachedSource->setCachedRange(
+ *offset, chunk_size,
+ mCachedSource != NULL /* assume ownership on success */) == OK) {
+ mDataSource = mCachedSource = cachedSource;
+ } else {
+ delete cachedSource;
}
}
@@ -3890,7 +3894,7 @@
MPEG4Source::MPEG4Source(
const sp<MetaData> &format,
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
int32_t timeScale,
const sp<SampleTable> &sampleTable,
Vector<SidxEntry> &sidx,
@@ -5379,7 +5383,7 @@
}
static bool LegacySniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ DataSourceBase *source, String8 *mimeType, float *confidence) {
uint8_t header[8];
ssize_t n = source->readAt(4, header, sizeof(header));
@@ -5446,7 +5450,7 @@
// (end of the 'moov' atom) and report it to the caller as part of
// the metadata.
static bool BetterSniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *meta) {
// We scan up to 128 bytes to identify this file as an MP4.
static const off64_t kMaxScanOffset = 128ll;
@@ -5563,13 +5567,13 @@
}
static MediaExtractor* CreateExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) {
return new MPEG4Extractor(source);
}
static MediaExtractor::CreatorFunc Sniff(
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *meta) {
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index e947b87..644c430 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -20,7 +20,7 @@
#include <arpa/inet.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaExtractor.h>
#include <media/stagefright/foundation/AString.h>
#include <utils/List.h>
@@ -29,7 +29,8 @@
namespace android {
struct AMessage;
-class DataSource;
+class DataSourceBase;
+struct CachedRangedDataSource;
class SampleTable;
class String8;
namespace heif {
@@ -52,8 +53,7 @@
class MPEG4Extractor : public MediaExtractor {
public:
- // Extractor assumes ownership of "source".
- explicit MPEG4Extractor(const sp<DataSource> &source, const char *mime = NULL);
+ explicit MPEG4Extractor(DataSourceBase *source, const char *mime = NULL);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -62,7 +62,6 @@
virtual sp<MetaData> getMetaData();
virtual uint32_t flags() const;
virtual const char * name() { return "MPEG4Extractor"; }
- virtual void release();
// for DRM
virtual char* getDrmTrackInfo(size_t trackID, int *len);
@@ -98,7 +97,8 @@
Vector<Trex> mTrex;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
+ CachedRangedDataSource *mCachedSource;
status_t mInitCheck;
uint32_t mHeaderTimescale;
bool mIsQT;
@@ -160,7 +160,7 @@
};
bool SniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/mp4/SampleIterator.cpp b/media/extractors/mp4/SampleIterator.cpp
index c194397..93ee7c6 100644
--- a/media/extractors/mp4/SampleIterator.cpp
+++ b/media/extractors/mp4/SampleIterator.cpp
@@ -22,7 +22,7 @@
#include <arpa/inet.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ByteUtils.h>
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index 378d63a..81c353e 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -25,7 +25,7 @@
#include <arpa/inet.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ByteUtils.h>
@@ -114,7 +114,7 @@
////////////////////////////////////////////////////////////////////////////////
-SampleTable::SampleTable(const sp<DataSource> &source)
+SampleTable::SampleTable(DataSourceBase *source)
: mDataSource(source),
mChunkOffsetOffset(-1),
mChunkOffsetType(0),
diff --git a/media/extractors/mp4/SampleTable.h b/media/extractors/mp4/SampleTable.h
index 466e26b..e4e974b 100644
--- a/media/extractors/mp4/SampleTable.h
+++ b/media/extractors/mp4/SampleTable.h
@@ -27,12 +27,12 @@
namespace android {
-class DataSource;
+class DataSourceBase;
struct SampleIterator;
class SampleTable : public RefBase {
public:
- explicit SampleTable(const sp<DataSource> &source);
+ explicit SampleTable(DataSourceBase *source);
bool isValid() const;
@@ -99,7 +99,7 @@
// Limit the total size of all internal tables to 200MiB.
static const size_t kMaxTotalSize = 200 * (1 << 20);
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
Mutex mLock;
off64_t mChunkOffsetOffset;
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index d5682e9..443d685 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -34,18 +34,18 @@
1,
"MPEG2-PS/TS Extractor",
[](
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
if (SniffMPEG2TS(source, mimeType, confidence, meta)) {
return [](
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) -> MediaExtractor* {
return new MPEG2TSExtractor(source);};
} else if (SniffMPEG2PS(source, mimeType, confidence, meta)) {
return [](
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) -> MediaExtractor* {
return new MPEG2PSExtractor(source);};
}
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 0978387..697e44f 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -23,7 +23,7 @@
#include "mpeg2ts/AnotherPacketSource.h"
#include "mpeg2ts/ESQueue.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -94,7 +94,7 @@
////////////////////////////////////////////////////////////////////////////////
-MPEG2PSExtractor::MPEG2PSExtractor(const sp<DataSource> &source)
+MPEG2PSExtractor::MPEG2PSExtractor(DataSourceBase *source)
: mDataSource(source),
mOffset(0),
mFinalResult(OK),
@@ -751,7 +751,7 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffMPEG2PS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
uint8_t header[5];
if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index f8a97ef..adf719a 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -31,7 +31,7 @@
class String8;
struct MPEG2PSExtractor : public MediaExtractor {
- explicit MPEG2PSExtractor(const sp<DataSource> &source);
+ explicit MPEG2PSExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -50,7 +50,7 @@
struct WrappedTrack;
mutable Mutex mLock;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
off64_t mOffset;
status_t mFinalResult;
@@ -72,7 +72,7 @@
};
bool SniffMPEG2PS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index b24e8db..6d0b1cc 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -22,7 +22,7 @@
#include "MPEG2TSExtractor.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/IStreamSource.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -121,7 +121,7 @@
////////////////////////////////////////////////////////////////////////////////
-MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
+MPEG2TSExtractor::MPEG2TSExtractor(DataSourceBase *source)
: mDataSource(source),
mParser(new ATSParser),
mLastSyncEvent(0),
@@ -367,7 +367,7 @@
}
status_t MPEG2TSExtractor::estimateDurationsFromTimesUsAtEnd() {
- if (!(mDataSource->flags() & DataSource::kIsLocalFileSource)) {
+ if (!(mDataSource->flags() & DataSourceBase::kIsLocalFileSource)) {
return ERROR_UNSUPPORTED;
}
@@ -646,7 +646,7 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffMPEG2TS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
for (int i = 0; i < 5; ++i) {
char header;
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index 362f016..57cb675 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -32,12 +32,12 @@
struct AMessage;
struct AnotherPacketSource;
struct ATSParser;
-class DataSource;
+class DataSourceBase;
struct MPEG2TSSource;
class String8;
struct MPEG2TSExtractor : public MediaExtractor {
- explicit MPEG2TSExtractor(const sp<DataSource> &source);
+ explicit MPEG2TSExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -55,7 +55,7 @@
mutable Mutex mLock;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<ATSParser> mParser;
@@ -79,9 +79,9 @@
// Try to feed more data from source to parser.
// |isInit| means this function is called inside init(). This is a signal to
// save SyncEvent so that init() can add SyncPoint after it updates |mSourceImpls|.
- // This function returns OK if expected amount of data is fed from DataSource to
+ // This function returns OK if expected amount of data is fed from DataSourceBase to
// parser and is successfully parsed. Otherwise, various error codes could be
- // returned, e.g., ERROR_END_OF_STREAM, or no data availalbe from DataSource, or
+ // returned, e.g., ERROR_END_OF_STREAM, or no data availalbe from DataSourceBase, or
// the data has syntax error during parsing, etc.
status_t feedMore(bool isInit = false);
status_t seek(int64_t seekTimeUs,
@@ -100,7 +100,7 @@
};
bool SniffMPEG2TS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index f62ec47..1d04bed 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -21,7 +21,7 @@
#include "OggExtractor.h"
#include <cutils/properties.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -69,7 +69,7 @@
struct MyOggExtractor {
MyOggExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const char *mimeType,
size_t numHeaders,
int64_t seekPreRollUs);
@@ -105,7 +105,7 @@
int64_t mTimeUs;
};
- sp<DataSource> mSource;
+ DataSourceBase *mSource;
off64_t mOffset;
Page mCurrentPage;
uint64_t mCurGranulePosition;
@@ -164,7 +164,7 @@
};
struct MyVorbisExtractor : public MyOggExtractor {
- explicit MyVorbisExtractor(const sp<DataSource> &source)
+ explicit MyVorbisExtractor(DataSourceBase *source)
: MyOggExtractor(source,
MEDIA_MIMETYPE_AUDIO_VORBIS,
/* numHeaders */ 3,
@@ -192,7 +192,7 @@
static const int32_t kOpusSampleRate = 48000;
static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms
- explicit MyOpusExtractor(const sp<DataSource> &source)
+ explicit MyOpusExtractor(DataSourceBase *source)
: MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs),
mChannelCount(0),
mCodecDelay(0),
@@ -294,7 +294,7 @@
////////////////////////////////////////////////////////////////////////////////
MyOggExtractor::MyOggExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const char *mimeType,
size_t numHeaders,
int64_t seekPreRollUs)
@@ -852,7 +852,7 @@
off64_t size;
uint64_t lastGranulePosition;
- if (!(mSource->flags() & DataSource::kIsCachingDataSource)
+ if (!(mSource->flags() & DataSourceBase::kIsCachingDataSource)
&& mSource->getSize(&size) == OK
&& findPrevGranulePosition(size, &lastGranulePosition) == OK) {
// Let's assume it's cheap to seek to the end.
@@ -1315,7 +1315,7 @@
////////////////////////////////////////////////////////////////////////////////
-OggExtractor::OggExtractor(const sp<DataSource> &source)
+OggExtractor::OggExtractor(DataSourceBase *source)
: mDataSource(source),
mInitCheck(NO_INIT),
mImpl(NULL) {
@@ -1370,13 +1370,13 @@
}
static MediaExtractor* CreateExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) {
return new OggExtractor(source);
}
static MediaExtractor::CreatorFunc Sniff(
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *) {
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index 126428c..c9c37eb 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -24,14 +24,14 @@
namespace android {
struct AMessage;
-class DataSource;
+class DataSourceBase;
class String8;
struct MyOggExtractor;
struct OggSource;
struct OggExtractor : public MediaExtractor {
- explicit OggExtractor(const sp<DataSource> &source);
+ explicit OggExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -46,7 +46,7 @@
private:
friend struct OggSource;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
status_t mInitCheck;
MyOggExtractor *mImpl;
@@ -56,7 +56,7 @@
};
bool SniffOgg(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ DataSourceBase *source, String8 *mimeType, float *confidence,
sp<AMessage> *);
} // namespace android
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index cf22c66..105a37f 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -21,7 +21,7 @@
#include "WAVExtractor.h"
#include <audio_utils/primitives.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/MediaSourceBase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -57,7 +57,7 @@
struct WAVSource : public MediaSourceBase {
WAVSource(
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
const sp<MetaData> &meta,
uint16_t waveFormat,
int32_t bitsPerSample,
@@ -78,7 +78,7 @@
private:
static const size_t kMaxFrameSize;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
sp<MetaData> mMeta;
uint16_t mWaveFormat;
int32_t mSampleRate;
@@ -94,7 +94,7 @@
WAVSource &operator=(const WAVSource &);
};
-WAVExtractor::WAVExtractor(const sp<DataSource> &source)
+WAVExtractor::WAVExtractor(DataSourceBase *source)
: mDataSource(source),
mValidFormat(false),
mChannelMask(CHANNEL_MASK_USE_CHANNEL_ORDER) {
@@ -348,7 +348,7 @@
const size_t WAVSource::kMaxFrameSize = 32768;
WAVSource::WAVSource(
- const sp<DataSource> &dataSource,
+ DataSourceBase *dataSource,
const sp<MetaData> &meta,
uint16_t waveFormat,
int32_t bitsPerSample,
@@ -545,13 +545,13 @@
////////////////////////////////////////////////////////////////////////////////
static MediaExtractor* CreateExtractor(
- const sp<DataSource> &source,
+ DataSourceBase *source,
const sp<AMessage>& meta __unused) {
return new WAVExtractor(source);
}
static MediaExtractor::CreatorFunc Sniff(
- const sp<DataSource> &source,
+ DataSourceBase *source,
String8 *mimeType,
float *confidence,
sp<AMessage> *) {
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index 47c3c40..67661ed 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -24,13 +24,12 @@
namespace android {
struct AMessage;
-class DataSource;
+class DataSourceBase;
class String8;
class WAVExtractor : public MediaExtractor {
public:
- // Extractor assumes ownership of "source".
- explicit WAVExtractor(const sp<DataSource> &source);
+ explicit WAVExtractor(DataSourceBase *source);
virtual size_t countTracks();
virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +41,7 @@
virtual ~WAVExtractor();
private:
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
status_t mInitCheck;
bool mValidFormat;
uint16_t mWaveFormat;
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1377005..3ac519b 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -254,6 +254,7 @@
srcs: [
"BufferingSettings.cpp",
+ "DataSourceDesc.cpp",
"IDataSource.cpp",
"IMediaExtractor.cpp",
"IMediaExtractorService.cpp",
diff --git a/media/libmedia/DataSourceDesc.cpp b/media/libmedia/DataSourceDesc.cpp
new file mode 100644
index 0000000..b7ccbce
--- /dev/null
+++ b/media/libmedia/DataSourceDesc.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "DataSourceDesc"
+
+#include <media/DataSource.h>
+#include <media/DataSourceDesc.h>
+#include <media/MediaHTTPService.h>
+
+namespace android {
+
+static const int64_t kLongMax = 0x7ffffffffffffffL;
+
+DataSourceDesc::DataSourceDesc()
+ : mType(TYPE_NONE),
+ mFDOffset(0),
+ mFDLength(kLongMax),
+ mId(0),
+ mStartPositionMs(0),
+ mEndPositionMs(0) {
+}
+
+} // namespace android
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index a8a7b82..51ccb5a 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -39,8 +39,7 @@
SETMEDIACAS,
SETUID,
NAME,
- GETMETRICS,
- RELEASE,
+ GETMETRICS
};
class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -140,13 +139,6 @@
ALOGV("name NOT IMPLEMENTED");
return NULL;
}
-
- virtual void release() {
- ALOGV("release");
- Parcel data, reply;
- data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
- remote()->transact(RELEASE, data, &reply);
- }
};
IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -224,12 +216,6 @@
reply->writeInt32(setMediaCas(casToken));
return OK;
}
- case RELEASE: {
- ALOGV("release");
- CHECK_INTERFACE(IMediaExtractor, data, reply);
- release();
- return OK;
- }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/MediaPlayer2Manager.cpp b/media/libmedia/MediaPlayer2Manager.cpp
index aefb91c..76b4c0b 100644
--- a/media/libmedia/MediaPlayer2Manager.cpp
+++ b/media/libmedia/MediaPlayer2Manager.cpp
@@ -45,6 +45,7 @@
#include <utils/Vector.h>
#include <media/AudioPolicyHelper.h>
+#include <media/DataSourceDesc.h>
#include <media/MediaHTTPService.h>
#include <media/MediaPlayer2EngineClient.h>
#include <media/MediaPlayer2Interface.h>
@@ -247,13 +248,6 @@
MediaPlayer2Manager gMediaPlayer2Manager;
-static bool checkPermission(const char* permissionString) {
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16(permissionString));
- if (!ok) ALOGE("Request requires %s", permissionString);
- return ok;
-}
-
// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
/* static */ int MediaPlayer2Manager::AudioOutput::mMinBufferCount = 4;
/* static */ bool MediaPlayer2Manager::AudioOutput::mIsOnEmulator = false;
@@ -284,6 +278,10 @@
sp<Client> c = new Client(
mPid, connId, client, audioSessionId, mUid);
+ if (!c->init()) {
+ return NULL;
+ }
+
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, mPid, mUid);
wp<Client> w = c;
@@ -514,6 +512,25 @@
#endif
}
+bool MediaPlayer2Manager::Client::init() {
+ sp<MediaPlayer2Interface> p = new NuPlayer2Driver(mPid);
+ status_t init_result = p->initCheck();
+ if (init_result != NO_ERROR) {
+ ALOGE("Failed to create player object, initCheck failed(%d)", init_result);
+ return false;
+ }
+
+ p->setNotifyCallback(this, notify);
+ p->setUID(mUid);
+ mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
+ mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
+ mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
+ p->setAudioSink(mAudioOutput);
+
+ mPlayer = p;
+ return true;
+}
+
MediaPlayer2Manager::Client::~Client()
{
ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
@@ -560,26 +577,6 @@
IPCThreadState::self()->flushCommands();
}
-sp<MediaPlayer2Interface> MediaPlayer2Manager::Client::createPlayer() {
- sp<MediaPlayer2Interface> p = getPlayer();
- if (p == NULL) {
- p = new NuPlayer2Driver(mPid);
- status_t init_result = p->initCheck();
- if (init_result == NO_ERROR) {
- p->setNotifyCallback(this, notify);
- } else {
- ALOGE("Failed to create player, initCheck failed(res = %d)", init_result);
- p.clear();
- }
- }
-
- if (p != NULL) {
- p->setUID(mUid);
- }
-
- return p;
-}
-
void MediaPlayer2Manager::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
audio_io_handle_t audioIo,
audio_port_handle_t deviceId) {
@@ -591,30 +588,20 @@
}
}
-sp<MediaPlayer2Interface> MediaPlayer2Manager::Client::setDataSource_pre() {
- sp<MediaPlayer2Interface> p = createPlayer();
+status_t MediaPlayer2Manager::Client::setDataSource(
+ const sp<DataSourceDesc> &dsd) {
+ sp<MediaPlayer2Interface> p = getPlayer();
if (p == NULL) {
- return p;
+ return NO_INIT;
}
- Mutex::Autolock lock(mLock);
+ if (dsd == NULL) {
+ return BAD_VALUE;
+ }
- mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
-
- mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
- mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
- p->setAudioSink(mAudioOutput);
-
- return p;
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource_post(
- const sp<MediaPlayer2Interface>& p,
- status_t status)
-{
- ALOGV(" setDataSource");
+ status_t status = p->setDataSource(dsd);
if (status != OK) {
- ALOGE(" error: %d", status);
+ ALOGE("setDataSource error: %d", status);
return status;
}
@@ -626,102 +613,9 @@
}
}
- if (status == OK) {
- Mutex::Autolock lock(mLock);
- mPlayer = p;
- }
return status;
}
-status_t MediaPlayer2Manager::Client::setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers)
-{
- ALOGV("setDataSource(%s)", url);
- if (url == NULL)
- return UNKNOWN_ERROR;
-
- if ((strncmp(url, "http://", 7) == 0) ||
- (strncmp(url, "https://", 8) == 0) ||
- (strncmp(url, "rtsp://", 7) == 0)) {
- if (!checkPermission("android.permission.INTERNET")) {
- return PERMISSION_DENIED;
- }
- }
-
- if (strncmp(url, "content://", 10) == 0) {
- ALOGE("setDataSource: content scheme is not supported here");
- mStatus = UNKNOWN_ERROR;
- return mStatus;
- } else {
- sp<MediaPlayer2Interface> p = setDataSource_pre();
- if (p == NULL) {
- return NO_INIT;
- }
-
- return mStatus =
- setDataSource_post(
- p, p->setDataSource(httpService, url, headers));
- }
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(int fd, int64_t offset, int64_t length)
-{
- ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
- fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
- struct stat sb;
- int ret = fstat(fd, &sb);
- if (ret != 0) {
- ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
- return UNKNOWN_ERROR;
- }
-
- ALOGV("st_dev = %llu", static_cast<unsigned long long>(sb.st_dev));
- ALOGV("st_mode = %u", sb.st_mode);
- ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
- ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
- ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
-
- if (offset >= sb.st_size) {
- ALOGE("offset error");
- return UNKNOWN_ERROR;
- }
- if (offset + length > sb.st_size) {
- length = sb.st_size - offset;
- ALOGV("calculated length = %lld", (long long)length);
- }
-
- sp<MediaPlayer2Interface> p = setDataSource_pre();
- if (p == NULL) {
- return NO_INIT;
- }
-
- // now set data source
- return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(
- const sp<IStreamSource> &source) {
- sp<MediaPlayer2Interface> p = setDataSource_pre();
- if (p == NULL) {
- return NO_INIT;
- }
-
- // now set data source
- return mStatus = setDataSource_post(p, p->setDataSource(source));
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(
- const sp<DataSource> &source) {
- sp<MediaPlayer2Interface> p = setDataSource_pre();
- if (p == NULL) {
- return NO_INIT;
- }
- // now set data source
- return mStatus = setDataSource_post(p, p->setDataSource(source));
-}
-
void MediaPlayer2Manager::Client::disconnectNativeWindow_l() {
if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
status_t err = native_window_api_disconnect(
@@ -1187,13 +1081,8 @@
ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
}
- sp<MediaPlayer2Interface> p = getPlayer();
-
// Right now, the only valid time to set a retransmit endpoint is before
- // player selection has been made (since the presence or absence of a
- // retransmit endpoint is going to determine which player is selected during
- // setDataSource).
- if (p != 0) return INVALID_OPERATION;
+ // setDataSource.
if (NULL != endpoint) {
Mutex::Autolock lock(mLock);
diff --git a/media/libmedia/MediaPlayer2Manager.h b/media/libmedia/MediaPlayer2Manager.h
index 20cc735..cdbbc70 100644
--- a/media/libmedia/MediaPlayer2Manager.h
+++ b/media/libmedia/MediaPlayer2Manager.h
@@ -287,22 +287,7 @@
const sp<media::VolumeShaper::Operation>& operation) override;
virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
- sp<MediaPlayer2Interface> createPlayer();
-
- virtual status_t setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers);
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-
- virtual status_t setDataSource(const sp<IStreamSource> &source);
- virtual status_t setDataSource(const sp<DataSource> &source);
-
-
- sp<MediaPlayer2Interface> setDataSource_pre();
- status_t setDataSource_post(const sp<MediaPlayer2Interface>& p,
- status_t status);
+ virtual status_t setDataSource(const sp<DataSourceDesc> &dsd);
static void notify(const wp<MediaPlayer2Engine> &listener, int msg,
int ext1, int ext2, const Parcel *obj);
@@ -343,6 +328,7 @@
uid_t uid);
Client();
virtual ~Client();
+ bool init();
void deletePlayer();
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index 4e5d67f..0896e75 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -47,7 +47,7 @@
mLength = size;
}
-MidiIoWrapper::MidiIoWrapper(const sp<DataSource> &source) {
+MidiIoWrapper::MidiIoWrapper(DataSourceBase *source) {
ALOGV("MidiIoWrapper(DataSource)");
mFd = -1;
mDataSource = source;
diff --git a/media/libmedia/include/media/DataSourceDesc.h b/media/libmedia/include/media/DataSourceDesc.h
new file mode 100644
index 0000000..c190261
--- /dev/null
+++ b/media/libmedia/include/media/DataSourceDesc.h
@@ -0,0 +1,68 @@
+/*
+ * 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_DATASOURCEDESC_H
+#define ANDROID_DATASOURCEDESC_H
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class DataSource;
+struct MediaHTTPService;
+
+// A binder interface for implementing a stagefright DataSource remotely.
+struct DataSourceDesc : public RefBase {
+public:
+ enum {
+ /* No data source has been set yet */
+ TYPE_NONE = 0,
+ /* data source is type of MediaDataSource */
+ TYPE_CALLBACK = 1,
+ /* data source is type of FileDescriptor */
+ TYPE_FD = 2,
+ /* data source is type of Url */
+ TYPE_URL = 3,
+ };
+
+ DataSourceDesc();
+
+ int mType;
+
+ sp<MediaHTTPService> mHttpService;
+ String8 mUrl;
+ KeyedVector<String8, String8> mHeaders;
+
+ int mFD;
+ int64_t mFDOffset;
+ int64_t mFDLength;
+
+ sp<DataSource> mCallbackSource;
+
+ int64_t mId;
+ int64_t mStartPositionMs;
+ int64_t mEndPositionMs;
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(DataSourceDesc);
+};
+
+}; // namespace android
+
+#endif // ANDROID_DATASOURCEDESC_H
diff --git a/media/libmedia/include/media/IMediaExtractor.h b/media/libmedia/include/media/IMediaExtractor.h
index 44f8c1d..9899429 100644
--- a/media/libmedia/include/media/IMediaExtractor.h
+++ b/media/libmedia/include/media/IMediaExtractor.h
@@ -68,8 +68,6 @@
virtual void setUID(uid_t uid) = 0;
virtual const char * name() = 0;
-
- virtual void release() = 0;
};
diff --git a/media/libmedia/include/media/MediaPlayer2Engine.h b/media/libmedia/include/media/MediaPlayer2Engine.h
index 00f5fb1..29df2d6 100644
--- a/media/libmedia/include/media/MediaPlayer2Engine.h
+++ b/media/libmedia/include/media/MediaPlayer2Engine.h
@@ -36,6 +36,7 @@
struct AudioPlaybackRate;
struct BufferingSettings;
class DataSource;
+struct DataSourceDesc;
struct IStreamSource;
struct MediaHTTPService;
class Parcel;
@@ -47,14 +48,7 @@
public:
virtual void disconnect() = 0;
- virtual status_t setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8>* headers) = 0;
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
- virtual status_t setDataSource(const sp<IStreamSource>& source) = 0;
- virtual status_t setDataSource(const sp<DataSource>& source) = 0;
+ virtual status_t setDataSource(const sp<DataSourceDesc>& source) = 0;
virtual status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) = 0;
virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) = 0;
diff --git a/media/libmedia/include/media/MediaPlayer2Interface.h b/media/libmedia/include/media/MediaPlayer2Interface.h
index 699618e..c2cc6e6 100644
--- a/media/libmedia/include/media/MediaPlayer2Interface.h
+++ b/media/libmedia/include/media/MediaPlayer2Interface.h
@@ -41,6 +41,7 @@
namespace android {
class DataSource;
+struct DataSourceDesc;
struct MediaHTTPService;
class Parcel;
struct ANativeWindowWrapper;
@@ -158,18 +159,7 @@
virtual void setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
- virtual status_t setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers = NULL) = 0;
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
-
- virtual status_t setDataSource(const sp<IStreamSource>& /* source */) {
- return INVALID_OPERATION;
- }
-
- virtual status_t setDataSource(const sp<DataSource>& /* source */) {
+ virtual status_t setDataSource(const sp<DataSourceDesc>& /* dsd */) {
return INVALID_OPERATION;
}
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 2754b2c..a27b410 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -19,7 +19,7 @@
#include <libsonivox/eas_types.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
namespace android {
@@ -27,7 +27,7 @@
public:
MidiIoWrapper(const char *path);
MidiIoWrapper(int fd, off64_t offset, int64_t size);
- MidiIoWrapper(const sp<DataSource> &source);
+ MidiIoWrapper(DataSourceBase *source);
~MidiIoWrapper();
@@ -40,7 +40,7 @@
int mFd;
off64_t mBase;
int64_t mLength;
- sp<DataSource> mDataSource;
+ DataSourceBase *mDataSource;
EAS_FILE mEasFile;
};
diff --git a/media/libmedia/include/media/mediaplayer2.h b/media/libmedia/include/media/mediaplayer2.h
index c96765f..f2fc901 100644
--- a/media/libmedia/include/media/mediaplayer2.h
+++ b/media/libmedia/include/media/mediaplayer2.h
@@ -36,6 +36,7 @@
struct AVSyncSettings;
struct ANativeWindowWrapper;
class DataSource;
+struct DataSourceDesc;
struct MediaHTTPService;
enum media2_event_type {
@@ -202,13 +203,7 @@
~MediaPlayer2();
void disconnect();
- status_t setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers);
-
- status_t setDataSource(int fd, int64_t offset, int64_t length);
- status_t setDataSource(const sp<DataSource> &source);
+ status_t setDataSource(const sp<DataSourceDesc> &dsd);
status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww);
status_t setListener(const sp<MediaPlayer2Listener>& listener);
status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
diff --git a/media/libmedia/mediaplayer2.cpp b/media/libmedia/mediaplayer2.cpp
index 5c34d4a..ba24da7 100644
--- a/media/libmedia/mediaplayer2.cpp
+++ b/media/libmedia/mediaplayer2.cpp
@@ -34,6 +34,7 @@
#include <media/AudioSystem.h>
#include <media/AVSyncSettings.h>
#include <media/DataSource.h>
+#include <media/DataSourceDesc.h>
#include <media/MediaAnalyticsItem.h>
#include <media/NdkWrapper.h>
@@ -153,43 +154,16 @@
return err;
}
-status_t MediaPlayer2::setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url, const KeyedVector<String8, String8> *headers)
+status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd)
{
- ALOGV("setDataSource(%s)", url);
- status_t err = BAD_VALUE;
- if (url != NULL) {
- sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
- if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
- (NO_ERROR != player->setDataSource(httpService, url, headers))) {
- player.clear();
- }
- err = attachNewPlayer(player);
+ if (dsd == NULL) {
+ return BAD_VALUE;
}
- return err;
-}
-
-status_t MediaPlayer2::setDataSource(int fd, int64_t offset, int64_t length)
-{
- ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
+ ALOGV("setDataSource type(%d)", dsd->mType);
status_t err = UNKNOWN_ERROR;
sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
- (NO_ERROR != player->setDataSource(fd, offset, length))) {
- player.clear();
- }
- err = attachNewPlayer(player);
- return err;
-}
-
-status_t MediaPlayer2::setDataSource(const sp<DataSource> &source)
-{
- ALOGV("setDataSource(DataSource)");
- status_t err = UNKNOWN_ERROR;
- sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
- if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
- (NO_ERROR != player->setDataSource(source))) {
+ (NO_ERROR != player->setDataSource(dsd))) {
player.clear();
}
err = attachNewPlayer(player);
diff --git a/media/libmedia/nuplayer2/NuPlayer2.cpp b/media/libmedia/nuplayer2/NuPlayer2.cpp
index 2c7f416..35e20e8 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2.cpp
@@ -43,6 +43,7 @@
#include <media/AudioParameter.h>
#include <media/AudioResamplerPublic.h>
#include <media/AVSyncSettings.h>
+#include <media/DataSourceDesc.h>
#include <media/MediaCodecBuffer.h>
#include <media/NdkWrapper.h>
@@ -258,16 +259,6 @@
mDriver = driver;
}
-void NuPlayer2::setDataSourceAsync(const sp<IStreamSource> &source) {
- sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
-
- sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-
- msg->setObject("source", new StreamingSource(notify, source));
- msg->post();
- mDataSourceType = DATA_SOURCE_TYPE_STREAM;
-}
-
static bool IsHTTPLiveURL(const char *url) {
if (!strncasecmp("http://", url, 7)
|| !strncasecmp("https://", url, 8)
@@ -285,93 +276,102 @@
return false;
}
-void NuPlayer2::setDataSourceAsync(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers) {
-
+void NuPlayer2::setDataSourceAsync(const sp<DataSourceDesc> &dsd) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
- size_t len = strlen(url);
-
sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-
sp<Source> source;
- if (IsHTTPLiveURL(url)) {
- source = new HTTPLiveSource(notify, httpService, url, headers);
- ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
- mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
- } else if (!strncasecmp(url, "rtsp://", 7)) {
- source = new RTSPSource(
- notify, httpService, url, headers, mUIDValid, mUID);
- ALOGV("setDataSourceAsync RTSPSource %s", url);
- mDataSourceType = DATA_SOURCE_TYPE_RTSP;
- } else if ((!strncasecmp(url, "http://", 7)
- || !strncasecmp(url, "https://", 8))
- && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
- || strstr(url, ".sdp?"))) {
- source = new RTSPSource(
- notify, httpService, url, headers, mUIDValid, mUID, true);
- ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
- mDataSourceType = DATA_SOURCE_TYPE_RTSP;
- } else {
- ALOGV("setDataSourceAsync GenericSource %s", url);
- sp<GenericSource> genericSource =
- new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+ switch (dsd->mType) {
+ case DataSourceDesc::TYPE_URL:
+ {
+ const char *url = dsd->mUrl.c_str();
+ size_t len = strlen(url);
- status_t err = genericSource->setDataSource(httpService, url, headers);
+ const sp<MediaHTTPService> &httpService = dsd->mHttpService;
+ KeyedVector<String8, String8> *headers = &(dsd->mHeaders);
- if (err == OK) {
- source = genericSource;
- } else {
- ALOGE("Failed to set data source!");
+ if (IsHTTPLiveURL(url)) {
+ source = new HTTPLiveSource(notify, httpService, url, headers);
+ ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
+ mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
+ } else if (!strncasecmp(url, "rtsp://", 7)) {
+ source = new RTSPSource(
+ notify, httpService, url, headers, mUIDValid, mUID);
+ ALOGV("setDataSourceAsync RTSPSource %s", url);
+ mDataSourceType = DATA_SOURCE_TYPE_RTSP;
+ } else if ((!strncasecmp(url, "http://", 7)
+ || !strncasecmp(url, "https://", 8))
+ && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
+ || strstr(url, ".sdp?"))) {
+ source = new RTSPSource(
+ notify, httpService, url, headers, mUIDValid, mUID, true);
+ ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
+ mDataSourceType = DATA_SOURCE_TYPE_RTSP;
+ } else {
+ ALOGV("setDataSourceAsync GenericSource %s", url);
+
+ sp<GenericSource> genericSource =
+ new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+
+ status_t err = genericSource->setDataSource(httpService, url, headers);
+
+ if (err == OK) {
+ source = genericSource;
+ } else {
+ ALOGE("Failed to set data source!");
+ }
+
+ // regardless of success/failure
+ mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
+ }
+ break;
}
- // regardless of success/failure
- mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
- }
- msg->setObject("source", source);
- msg->post();
-}
+ case DataSourceDesc::TYPE_FD:
+ {
+ sp<GenericSource> genericSource =
+ new GenericSource(notify, mUIDValid, mUID, mMediaClock);
-void NuPlayer2::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
- sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
+ ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
+ dsd->mFD, (long long)dsd->mFDOffset, (long long)dsd->mFDLength, source.get());
- sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
+ status_t err = genericSource->setDataSource(dsd->mFD, dsd->mFDOffset, dsd->mFDLength);
- sp<GenericSource> source =
- new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+ if (err != OK) {
+ ALOGE("Failed to set data source!");
+ source = NULL;
+ } else {
+ source = genericSource;
+ }
- ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
- fd, (long long)offset, (long long)length, source.get());
+ mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
+ break;
+ }
- status_t err = source->setDataSource(fd, offset, length);
+ case DataSourceDesc::TYPE_CALLBACK:
+ {
+ sp<GenericSource> genericSource =
+ new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+ status_t err = genericSource->setDataSource(dsd->mCallbackSource);
- if (err != OK) {
- ALOGE("Failed to set data source!");
- source = NULL;
+ if (err != OK) {
+ ALOGE("Failed to set data source!");
+ source = NULL;
+ } else {
+ source = genericSource;
+ }
+
+ mDataSourceType = DATA_SOURCE_TYPE_MEDIA;
+ break;
+ }
+
+ default:
+ ALOGE("invalid data source type!");
+ break;
}
msg->setObject("source", source);
msg->post();
- mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
-}
-
-void NuPlayer2::setDataSourceAsync(const sp<DataSource> &dataSource) {
- sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
- sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-
- sp<GenericSource> source = new GenericSource(notify, mUIDValid, mUID, mMediaClock);
- status_t err = source->setDataSource(dataSource);
-
- if (err != OK) {
- ALOGE("Failed to set data source!");
- source = NULL;
- }
-
- msg->setObject("source", source);
- msg->post();
- mDataSourceType = DATA_SOURCE_TYPE_MEDIA;
}
status_t NuPlayer2::getBufferingSettings(
diff --git a/media/libmedia/nuplayer2/NuPlayer2.h b/media/libmedia/nuplayer2/NuPlayer2.h
index 23c4fdf..0764ec3 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.h
+++ b/media/libmedia/nuplayer2/NuPlayer2.h
@@ -30,6 +30,7 @@
struct ANativeWindowWrapper;
struct AudioPlaybackRate;
struct AVSyncSettings;
+struct DataSourceDesc;
class IDataSource;
struct MediaClock;
struct MediaHTTPService;
@@ -43,16 +44,7 @@
void setDriver(const wp<NuPlayer2Driver> &driver);
- void setDataSourceAsync(const sp<IStreamSource> &source);
-
- void setDataSourceAsync(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers);
-
- void setDataSourceAsync(int fd, int64_t offset, int64_t length);
-
- void setDataSourceAsync(const sp<DataSource> &source);
+ void setDataSourceAsync(const sp<DataSourceDesc> &dsd);
status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
status_t setBufferingSettings(const BufferingSettings& buffering);
diff --git a/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp b/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp
index 4d80912..9c1988f 100644
--- a/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp
@@ -39,7 +39,9 @@
// are blocking, but NuPlayer2 needs asynchronous operations.
mDecoderLooper = new ALooper;
mDecoderLooper->setName("NPDecoder");
- mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+ mDecoderLooper->start(false, /* runOnCallingThread */
+ true, /* canCallJava */
+ ANDROID_PRIORITY_AUDIO);
}
NuPlayer2::DecoderBase::~DecoderBase() {
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
index e48acea..6137fd1 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
@@ -175,67 +175,7 @@
return OK;
}
-status_t NuPlayer2Driver::setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers) {
- ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str());
- Mutex::Autolock autoLock(mLock);
-
- if (mState != STATE_IDLE) {
- return INVALID_OPERATION;
- }
-
- mState = STATE_SET_DATASOURCE_PENDING;
-
- mPlayer->setDataSourceAsync(httpService, url, headers);
-
- while (mState == STATE_SET_DATASOURCE_PENDING) {
- mCondition.wait(mLock);
- }
-
- return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::setDataSource(int fd, int64_t offset, int64_t length) {
- ALOGV("setDataSource(%p) file(%d)", this, fd);
- Mutex::Autolock autoLock(mLock);
-
- if (mState != STATE_IDLE) {
- return INVALID_OPERATION;
- }
-
- mState = STATE_SET_DATASOURCE_PENDING;
-
- mPlayer->setDataSourceAsync(fd, offset, length);
-
- while (mState == STATE_SET_DATASOURCE_PENDING) {
- mCondition.wait(mLock);
- }
-
- return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::setDataSource(const sp<IStreamSource> &source) {
- ALOGV("setDataSource(%p) stream source", this);
- Mutex::Autolock autoLock(mLock);
-
- if (mState != STATE_IDLE) {
- return INVALID_OPERATION;
- }
-
- mState = STATE_SET_DATASOURCE_PENDING;
-
- mPlayer->setDataSourceAsync(source);
-
- while (mState == STATE_SET_DATASOURCE_PENDING) {
- mCondition.wait(mLock);
- }
-
- return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::setDataSource(const sp<DataSource> &source) {
+status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
ALOGV("setDataSource(%p) callback source", this);
Mutex::Autolock autoLock(mLock);
@@ -245,7 +185,7 @@
mState = STATE_SET_DATASOURCE_PENDING;
- mPlayer->setDataSourceAsync(source);
+ mPlayer->setDataSourceAsync(dsd);
while (mState == STATE_SET_DATASOURCE_PENDING) {
mCondition.wait(mLock);
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.h b/media/libmedia/nuplayer2/NuPlayer2Driver.h
index 7bbb367..55fc9ef 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.h
@@ -32,16 +32,7 @@
virtual status_t setUID(uid_t uid);
- virtual status_t setDataSource(
- const sp<MediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers);
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-
- virtual status_t setDataSource(const sp<IStreamSource> &source);
-
- virtual status_t setDataSource(const sp<DataSource>& dataSource);
+ virtual status_t setDataSource(const sp<DataSourceDesc> &dsd) override;
virtual status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww);
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 4071fba..8f4ba70 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -23,7 +23,7 @@
],
srcs: [
- "DataSource.cpp",
+ "DataSourceBase.cpp",
"MediaBuffer.cpp",
"MediaBufferGroup.cpp",
"MediaSourceBase.cpp",
diff --git a/media/libmediaextractor/DataSource.cpp b/media/libmediaextractor/DataSourceBase.cpp
similarity index 77%
rename from media/libmediaextractor/DataSource.cpp
rename to media/libmediaextractor/DataSourceBase.cpp
index 72959c6..d3af4eb 100644
--- a/media/libmediaextractor/DataSource.cpp
+++ b/media/libmediaextractor/DataSourceBase.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "DataSource"
+#define LOG_TAG "DataSourceBase"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/String8.h>
namespace android {
-bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
+bool DataSourceBase::getUInt16(off64_t offset, uint16_t *x) {
*x = 0;
uint8_t byte[2];
@@ -36,7 +36,7 @@
return true;
}
-bool DataSource::getUInt24(off64_t offset, uint32_t *x) {
+bool DataSourceBase::getUInt24(off64_t offset, uint32_t *x) {
*x = 0;
uint8_t byte[3];
@@ -49,7 +49,7 @@
return true;
}
-bool DataSource::getUInt32(off64_t offset, uint32_t *x) {
+bool DataSourceBase::getUInt32(off64_t offset, uint32_t *x) {
*x = 0;
uint32_t tmp;
@@ -62,7 +62,7 @@
return true;
}
-bool DataSource::getUInt64(off64_t offset, uint64_t *x) {
+bool DataSourceBase::getUInt64(off64_t offset, uint64_t *x) {
*x = 0;
uint64_t tmp;
@@ -75,7 +75,7 @@
return true;
}
-bool DataSource::getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
+bool DataSourceBase::getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
if (size == 2) {
return getUInt16(offset, x);
}
@@ -89,7 +89,7 @@
return false;
}
-bool DataSource::getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
+bool DataSourceBase::getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
if (size == 4) {
return getUInt32(offset, x);
}
@@ -103,7 +103,7 @@
return false;
}
-bool DataSource::getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
+bool DataSourceBase::getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
if (size == 8) {
return getUInt64(offset, x);
}
@@ -117,13 +117,13 @@
return false;
}
-status_t DataSource::getSize(off64_t *size) {
+status_t DataSourceBase::getSize(off64_t *size) {
*size = 0;
return ERROR_UNSUPPORTED;
}
-String8 DataSource::getMIMEType() const {
+String8 DataSourceBase::getMIMEType() const {
return String8("application/octet-stream");
}
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index 9f00e0a..a066183 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -20,75 +20,21 @@
#include <sys/types.h>
#include <media/stagefright/MediaErrors.h>
+#include <media/DataSourceBase.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
#include <drm/DrmManagerClient.h>
+
namespace android {
class String8;
-class DataSource : public RefBase {
+class DataSource : public DataSourceBase, public virtual RefBase {
public:
- enum Flags {
- kWantsPrefetching = 1,
- kStreamedFromLocalHost = 2,
- kIsCachingDataSource = 4,
- kIsHTTPBasedSource = 8,
- kIsLocalFileSource = 16,
- };
-
DataSource() {}
- virtual status_t initCheck() const = 0;
-
- // Returns the number of bytes read, or -1 on failure. It's not an error if
- // this returns zero; it just means the given offset is equal to, or
- // beyond, the end of the source.
- virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
-
- // Convenience methods:
- bool getUInt16(off64_t offset, uint16_t *x);
- bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int
- bool getUInt32(off64_t offset, uint32_t *x);
- bool getUInt64(off64_t offset, uint64_t *x);
-
- // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
- bool getUInt16Var(off64_t offset, uint16_t *x, size_t size);
- bool getUInt32Var(off64_t offset, uint32_t *x, size_t size);
- bool getUInt64Var(off64_t offset, uint64_t *x, size_t size);
-
- // May return ERROR_UNSUPPORTED.
- virtual status_t getSize(off64_t *size);
-
- virtual uint32_t flags() {
- return 0;
- }
-
- virtual String8 toString() {
- return String8("<unspecified>");
- }
-
- virtual status_t reconnectAtOffset(off64_t /*offset*/) {
- return ERROR_UNSUPPORTED;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // for DRM
- virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
- return NULL;
- }
-
- virtual String8 getUri() {
- return String8();
- }
-
- virtual String8 getMIMEType() const;
-
- virtual void close() {};
-
protected:
virtual ~DataSource() {}
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libmediaextractor/include/media/DataSourceBase.h
new file mode 100644
index 0000000..f964137
--- /dev/null
+++ b/media/libmediaextractor/include/media/DataSourceBase.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 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 DATA_SOURCE_BASE_H_
+
+#define DATA_SOURCE_BASE_H_
+
+#include <sys/types.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+class String8;
+
+class DataSourceBase {
+public:
+ enum Flags {
+ kWantsPrefetching = 1,
+ kStreamedFromLocalHost = 2,
+ kIsCachingDataSource = 4,
+ kIsHTTPBasedSource = 8,
+ kIsLocalFileSource = 16,
+ };
+
+ DataSourceBase() {}
+
+ virtual status_t initCheck() const = 0;
+
+ // Returns the number of bytes read, or -1 on failure. It's not an error if
+ // this returns zero; it just means the given offset is equal to, or
+ // beyond, the end of the source.
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
+
+ // Convenience methods:
+ bool getUInt16(off64_t offset, uint16_t *x);
+ bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int
+ bool getUInt32(off64_t offset, uint32_t *x);
+ bool getUInt64(off64_t offset, uint64_t *x);
+
+ // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
+ bool getUInt16Var(off64_t offset, uint16_t *x, size_t size);
+ bool getUInt32Var(off64_t offset, uint32_t *x, size_t size);
+ bool getUInt64Var(off64_t offset, uint64_t *x, size_t size);
+
+ // Reads in "count" entries of type T into vector *x.
+ // Returns true if "count" entries can be read.
+ // If fewer than "count" entries can be read, return false. In this case,
+ // the output vector *x will still have those entries that were read. Call
+ // x->size() to obtain the number of entries read.
+ // The optional parameter chunkSize specifies how many entries should be
+ // read from the data source at one time into a temporary buffer. Increasing
+ // chunkSize can improve the performance at the cost of extra memory usage.
+ // The default value for chunkSize is set to read at least 4k bytes at a
+ // time, depending on sizeof(T).
+ template <typename T>
+ bool getVector(off64_t offset, Vector<T>* x, size_t count,
+ size_t chunkSize = (4095 / sizeof(T)) + 1);
+
+ // May return ERROR_UNSUPPORTED.
+ virtual status_t getSize(off64_t *size);
+
+ virtual uint32_t flags() {
+ return 0;
+ }
+
+ virtual String8 toString() {
+ return String8("<unspecified>");
+ }
+
+ virtual status_t reconnectAtOffset(off64_t /*offset*/) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // for DRM
+ virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
+ return NULL;
+ }
+
+ virtual String8 getUri() {
+ return String8();
+ }
+
+ virtual String8 getMIMEType() const;
+
+ virtual void close() {};
+
+protected:
+ virtual ~DataSourceBase() {}
+
+private:
+ DataSourceBase(const DataSourceBase &);
+ DataSourceBase &operator=(const DataSourceBase &);
+};
+
+template <typename T>
+bool DataSourceBase::getVector(off64_t offset, Vector<T>* x, size_t count,
+ size_t chunkSize)
+{
+ x->clear();
+ if (chunkSize == 0) {
+ return false;
+ }
+ if (count == 0) {
+ return true;
+ }
+
+ T tmp[chunkSize];
+ ssize_t numBytesRead;
+ size_t numBytesPerChunk = chunkSize * sizeof(T);
+ size_t i;
+
+ for (i = 0; i + chunkSize < count; i += chunkSize) {
+ // This loops is executed when more than chunkSize records need to be
+ // read.
+ numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk);
+ if (numBytesRead == -1) { // If readAt() returns -1, there is an error.
+ return false;
+ }
+ if (static_cast<size_t>(numBytesRead) < numBytesPerChunk) {
+ // This case is triggered when the stream ends before the whole
+ // chunk is read.
+ x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+ return false;
+ }
+ x->appendArray(tmp, chunkSize);
+ offset += numBytesPerChunk;
+ }
+
+ // There are (count - i) more records to read.
+ // Right now, (count - i) <= chunkSize.
+ // We do the same thing as above, but with chunkSize replaced by count - i.
+ numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T));
+ if (numBytesRead == -1) {
+ return false;
+ }
+ x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+ return x->size() == count;
+}
+
+} // namespace android
+
+#endif // DATA_SOURCE_BASE_H_
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index 27581f3..60495ec 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -27,7 +27,7 @@
namespace android {
-class DataSource;
+class DataSourceBase;
class MetaData;
class String8;
struct AMessage;
@@ -87,15 +87,14 @@
virtual const char * name() { return "<unspecified>"; }
- virtual void release() {}
typedef MediaExtractor* (*CreatorFunc)(
- const sp<DataSource> &source, const sp<AMessage> &meta);
+ DataSourceBase *source, const sp<AMessage> &meta);
// The sniffer can optionally fill in "meta" with an AMessage containing
// a dictionary of values that helps the corresponding extractor initialize
// its state without duplicating effort already exerted by the sniffer.
typedef CreatorFunc (*SnifferFunc)(
- const sp<DataSource> &source, String8 *mimeType,
+ DataSourceBase *source, String8 *mimeType,
float *confidence, sp<AMessage> *meta);
typedef struct {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 329b901..5240f7b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -137,6 +137,8 @@
"libRScpp",
"libhidlbase",
"libhidlmemory",
+ // TODO: Remove libv4l2_c2_componentstore.
+ "libv4l2_c2componentstore",
"libziparchive",
"android.hidl.allocator@1.0",
"android.hardware.cas.native@1.0",
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
index 9fb6d34..bd2443d 100644
--- a/media/libstagefright/BufferImpl.cpp
+++ b/media/libstagefright/BufferImpl.cpp
@@ -64,28 +64,51 @@
return ICrypto::kDestinationTypeNativeHandle;
}
-// Codec2Buffer
+// LinearBlockBuffer
// static
-sp<Codec2Buffer> Codec2Buffer::allocate(
+sp<LinearBlockBuffer> LinearBlockBuffer::allocate(
const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
C2WriteView writeView(block->map().get());
if (writeView.error() != C2_OK) {
return nullptr;
}
- return new Codec2Buffer(format, new ABuffer(writeView.base(), writeView.capacity()), block);
+ return new LinearBlockBuffer(format, std::move(writeView), block);
}
-C2ConstLinearBlock Codec2Buffer::share() {
+C2ConstLinearBlock LinearBlockBuffer::share() {
return mBlock->share(offset(), size(), C2Fence());
}
-Codec2Buffer::Codec2Buffer(
+LinearBlockBuffer::LinearBlockBuffer(
const sp<AMessage> &format,
- const sp<ABuffer> &buffer,
+ C2WriteView&& writeView,
const std::shared_ptr<C2LinearBlock> &block)
- : MediaCodecBuffer(format, buffer),
+ : MediaCodecBuffer(format, new ABuffer(writeView.data(), writeView.size())),
+ mWriteView(writeView),
mBlock(block) {
}
+// ConstLinearBlockBuffer
+
+// static
+sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::allocate(
+ const sp<AMessage> &format, const C2ConstLinearBlock &block) {
+ C2ReadView readView(block.map().get());
+ if (readView.error() != C2_OK) {
+ return nullptr;
+ }
+ return new ConstLinearBlockBuffer(format, std::move(readView));
+}
+
+ConstLinearBlockBuffer::ConstLinearBlockBuffer(
+ const sp<AMessage> &format,
+ C2ReadView&& readView)
+ : MediaCodecBuffer(format, new ABuffer(
+ // NOTE: ABuffer only takes non-const pointer but this data is
+ // supposed to be read-only.
+ const_cast<uint8_t *>(readView.data()), readView.capacity())),
+ mReadView(readView) {
+}
+
} // namespace android
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
index 1e0a53f..84e98f8 100644
--- a/media/libstagefright/CCodec.cpp
+++ b/media/libstagefright/CCodec.cpp
@@ -16,11 +16,13 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "CCodec"
+#include <cutils/properties.h>
#include <utils/Log.h>
#include <thread>
#include <C2PlatformSupport.h>
+#include <C2V4l2Support.h>
#include <gui/Surface.h>
#include <media/stagefright/BufferProducerWrapper.h>
@@ -187,7 +189,14 @@
std::shared_ptr<C2Component> comp;
c2_status_t err = GetCodec2PlatformComponentStore()->createComponent(
componentName.c_str(), &comp);
+ static bool v4l2Enabled =
+ property_get_bool("debug.stagefright.ccodec_v4l2", false);
+ if (err != C2_OK && v4l2Enabled) {
+ err = GetCodec2VDAComponentStore()->createComponent(
+ componentName.c_str(), &comp);
+ }
if (err != C2_OK) {
+ ALOGE("Failed Create component: %s", componentName.c_str());
Mutexed<State>::Locked state(mState);
state->set(RELEASED);
state.unlock();
@@ -195,6 +204,7 @@
state.lock();
return;
}
+ ALOGV("Success Create component: %s", componentName.c_str());
comp->setListener_vb(mListener, C2_MAY_BLOCK);
{
Mutexed<State>::Locked state(mState);
diff --git a/media/libstagefright/CCodecBufferChannel.cpp b/media/libstagefright/CCodecBufferChannel.cpp
index 04f7593..ca4ddc8 100644
--- a/media/libstagefright/CCodecBufferChannel.cpp
+++ b/media/libstagefright/CCodecBufferChannel.cpp
@@ -249,7 +249,7 @@
return std::distance(buffers->begin(), it);
}
-sp<Codec2Buffer> allocateLinearBuffer(
+sp<LinearBlockBuffer> allocateLinearBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const sp<AMessage> &format,
size_t size,
@@ -264,7 +264,7 @@
return nullptr;
}
- return Codec2Buffer::allocate(format, block);
+ return LinearBlockBuffer::allocate(format, block);
}
class Buffer1D : public C2Buffer {
@@ -283,7 +283,7 @@
void add(
size_t index,
- const sp<Codec2Buffer> &clientBuffer,
+ const sp<LinearBlockBuffer> &clientBuffer,
bool available) {
if (mBufferArray.size() <= index) {
// TODO: make this more efficient
@@ -340,7 +340,7 @@
private:
struct Entry {
- sp<Codec2Buffer> clientBuffer;
+ sp<LinearBlockBuffer> clientBuffer;
std::weak_ptr<C2Buffer> compBuffer;
bool available;
};
@@ -354,7 +354,7 @@
bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
*buffer = nullptr;
- ssize_t ret = findBufferSlot<wp<Codec2Buffer>>(
+ ssize_t ret = findBufferSlot<wp<LinearBlockBuffer>>(
&mBuffers, kMinBufferArraySize,
[] (const auto &elem) { return elem.promote() == nullptr; });
if (ret < 0) {
@@ -363,7 +363,7 @@
// TODO: proper max input size and usage
// TODO: read usage from intf
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- sp<Codec2Buffer> newBuffer = allocateLinearBuffer(mPool, mFormat, kLinearBufferSize, usage);
+ sp<LinearBlockBuffer> newBuffer = allocateLinearBuffer(mPool, mFormat, kLinearBufferSize, usage);
if (newBuffer == nullptr) {
return false;
}
@@ -378,7 +378,7 @@
if (it == mBuffers.end()) {
return nullptr;
}
- sp<Codec2Buffer> codecBuffer = it->promote();
+ sp<LinearBlockBuffer> codecBuffer = it->promote();
// We got sp<> reference from the caller so this should never happen..
CHECK(codecBuffer != nullptr);
return std::make_shared<Buffer1D>(codecBuffer->share());
@@ -394,7 +394,7 @@
const size_t size = std::max(kMinBufferArraySize, mBuffers.size());
mBuffers.resize(size);
for (size_t i = 0; i < size; ++i) {
- sp<Codec2Buffer> clientBuffer = mBuffers[i].promote();
+ sp<LinearBlockBuffer> clientBuffer = mBuffers[i].promote();
bool available = false;
if (clientBuffer == nullptr) {
// TODO: proper max input size
@@ -414,7 +414,7 @@
private:
// Buffers we passed to the client. The index of a buffer matches what
// was passed in BufferCallback::onInputBufferAvailable().
- std::vector<wp<Codec2Buffer>> mBuffers;
+ std::vector<wp<LinearBlockBuffer>> mBuffers;
};
class GraphicInputBuffers : public CCodecBufferChannel::InputBuffers {
@@ -617,9 +617,7 @@
if (ret < 0) {
return false;
}
- sp<MediaCodecBuffer> newBuffer = new MediaCodecBuffer(
- mFormat,
- convert(buffer));
+ sp<MediaCodecBuffer> newBuffer = convert(buffer);
mBuffers[ret] = { newBuffer, buffer };
*index = ret;
*codecBuffer = newBuffer;
@@ -669,7 +667,7 @@
// track of the flushed work.
}
- virtual sp<ABuffer> convert(const std::shared_ptr<C2Buffer> &buffer) = 0;
+ virtual sp<MediaCodecBuffer> convert(const std::shared_ptr<C2Buffer> &buffer) = 0;
protected:
struct BufferInfo {
@@ -687,9 +685,9 @@
public:
using FlexOutputBuffers::FlexOutputBuffers;
- virtual sp<ABuffer> convert(const std::shared_ptr<C2Buffer> &buffer) override {
+ virtual sp<MediaCodecBuffer> convert(const std::shared_ptr<C2Buffer> &buffer) override {
if (buffer == nullptr) {
- return new ABuffer(nullptr, 0);
+ return new MediaCodecBuffer(mFormat, new ABuffer(nullptr, 0));
}
if (buffer->data().type() != C2BufferData::LINEAR) {
// We expect linear output buffers from the component.
@@ -699,16 +697,7 @@
// We expect one and only one linear block from the component.
return nullptr;
}
- C2ReadView view = buffer->data().linearBlocks().front().map().get();
- if (view.error() != C2_OK) {
- // Mapping the linear block failed
- return nullptr;
- }
- return new ABuffer(
- // XXX: the data is supposed to be read-only. We don't have
- // const equivalent of ABuffer however...
- const_cast<uint8_t *>(view.data()),
- view.capacity());
+ return ConstLinearBlockBuffer::allocate(mFormat, buffer->data().linearBlocks().front());
}
std::unique_ptr<CCodecBufferChannel::OutputBuffers> toArrayMode() override {
@@ -737,8 +726,9 @@
public:
using FlexOutputBuffers::FlexOutputBuffers;
- sp<ABuffer> convert(const std::shared_ptr<C2Buffer> &buffer) override {
- return buffer ? new ABuffer(nullptr, 1) : new ABuffer(nullptr, 0);
+ sp<MediaCodecBuffer> convert(const std::shared_ptr<C2Buffer> &buffer) override {
+ return new MediaCodecBuffer(
+ mFormat, buffer ? new ABuffer(nullptr, 1) : new ABuffer(nullptr, 0));
}
std::unique_ptr<CCodecBufferChannel::OutputBuffers> toArrayMode() override {
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index f479644..71b737b 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -21,6 +21,7 @@
#include "include/CallbackDataSource.h"
#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
#include <media/IDataSource.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -34,7 +35,10 @@
mIsClosed(false) {
// Set up the buffer to read into.
mMemory = mIDataSource->getIMemory();
- mName = String8::format("CallbackDataSource(%s)", mIDataSource->toString().string());
+ mName = String8::format("CallbackDataSource(%d->%d, %s)",
+ getpid(),
+ IPCThreadState::self()->getCallingPid(),
+ mIDataSource->toString().string());
}
diff --git a/media/libstagefright/InterfaceUtils.cpp b/media/libstagefright/InterfaceUtils.cpp
index 284e63b..70fbbd7 100644
--- a/media/libstagefright/InterfaceUtils.cpp
+++ b/media/libstagefright/InterfaceUtils.cpp
@@ -38,11 +38,13 @@
}
sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(
- MediaExtractor *extractor, const sp<RefBase> &plugin) {
+ MediaExtractor *extractor,
+ const sp<DataSource> &source,
+ const sp<RefBase> &plugin) {
if (extractor == nullptr) {
return nullptr;
}
- return RemoteMediaExtractor::wrap(extractor, plugin);
+ return RemoteMediaExtractor::wrap(extractor, source, plugin);
}
sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source) {
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index e79696c..bb72167 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -118,7 +118,7 @@
String8 tmp;
float confidence;
sp<ExtractorPlugin> plugin;
- creator = sniff(source, &tmp, &confidence, &meta, plugin);
+ creator = sniff(source.get(), &tmp, &confidence, &meta, plugin);
if (!creator) {
ALOGV("FAILED to autodetect media content.");
return NULL;
@@ -128,8 +128,8 @@
ALOGV("Autodetected media content as '%s' with confidence %.2f",
mime, confidence);
- MediaExtractor *ret = creator(source, meta);
- return CreateIMediaExtractorFromMediaExtractor(ret, plugin);
+ MediaExtractor *ret = creator(source.get(), meta);
+ return CreateIMediaExtractorFromMediaExtractor(ret, source, plugin);
}
//static
@@ -165,7 +165,7 @@
// static
MediaExtractor::CreatorFunc MediaExtractorFactory::sniff(
- const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta,
+ DataSourceBase *source, String8 *mimeType, float *confidence, sp<AMessage> *meta,
sp<ExtractorPlugin> &plugin) {
*mimeType = "";
*confidence = 0.0f;
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 3ebee51..601c9fa 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -37,9 +37,12 @@
static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
RemoteMediaExtractor::RemoteMediaExtractor(
- MediaExtractor *extractor, const sp<RefBase> &plugin)
+ MediaExtractor *extractor,
+ const sp<DataSource> &source,
+ const sp<RefBase> &plugin)
:mExtractor(extractor),
- mExtractorPlugin(plugin) {
+ mSource(source),
+ mExtractorPlugin(plugin) {
mAnalyticsItem = nullptr;
if (MEDIA_LOG) {
@@ -67,6 +70,8 @@
RemoteMediaExtractor::~RemoteMediaExtractor() {
delete mExtractor;
+ mSource->close();
+ mSource.clear();
mExtractorPlugin = nullptr;
// log the current record, provided it has some information worth recording
if (MEDIA_LOG) {
@@ -129,19 +134,17 @@
return mExtractor->name();
}
-void RemoteMediaExtractor::release() {
- return mExtractor->release();
-}
-
////////////////////////////////////////////////////////////////////////////////
// static
sp<IMediaExtractor> RemoteMediaExtractor::wrap(
- MediaExtractor *extractor, const sp<RefBase> &plugin) {
+ MediaExtractor *extractor,
+ const sp<DataSource> &source,
+ const sp<RefBase> &plugin) {
if (extractor == nullptr) {
return nullptr;
}
- return new RemoteMediaExtractor(extractor, plugin);
+ return new RemoteMediaExtractor(extractor, source, plugin);
}
} // namespace android
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index e2db0f5..179e0e6 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -47,12 +47,6 @@
StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
ALOGV("~StagefrightMetadataRetriever()");
clearMetadata();
- // Explicitly release extractor before continuing with the destructor,
- // some extractors might need to callback to close off the DataSource
- // and we need to make sure it's still there.
- if (mExtractor != NULL) {
- mExtractor->release();
- }
if (mSource != NULL) {
mSource->close();
}
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index 442c89e..ab81cdc 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -189,6 +189,7 @@
#define C2_CONST __attribute__((const))
#define C2_HIDE __attribute__((visibility("hidden")))
#define C2_INTERNAL __attribute__((internal_linkage))
+#define C2_ALLOW_OVERFLOW __attribute__((no_sanitize("integer")))
#define DEFINE_OTHER_COMPARISON_OPERATORS(type) \
inline bool operator!=(const type &other) const { return !(*this == other); } \
@@ -221,13 +222,13 @@
template<typename T>
struct C2_HIDE _c2_cntr_compat_helper {
template<typename U, typename E=typename std::enable_if<std::is_integral<U>::value>::type>
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline static constexpr T get(const U &value) {
return T(value);
}
template<typename U, typename E=typename std::enable_if<(sizeof(U) >= sizeof(T))>::type>
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline static constexpr T get(const c2_cntr_t<U, void> &value) {
return T(value.mValue);
}
@@ -281,7 +282,7 @@
/**
* Peek as underlying signed type.
*/
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline constexpr typename std::make_signed<T>::type peek() const {
return static_cast<typename std::make_signed<T>::type>(mValue);
}
@@ -296,7 +297,7 @@
/**
* Peek as long long - e.g. for printing.
*/
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline constexpr long long peekll() const {
return (long long)mValue;
}
@@ -304,7 +305,7 @@
/**
* Peek as unsigned long long - e.g. for printing.
*/
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline constexpr unsigned long long peekull() const {
return (unsigned long long)mValue;
}
@@ -352,24 +353,24 @@
return c2_cntr_t<T, void>(mValue op); \
}
- DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), +, +=)
- DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), -, -=)
- DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), *, *=)
+ DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, +, +=)
+ DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, -, -=)
+ DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, *, *=)
- DEFINE_C2_CNTR_UNARY_OP(__attribute__((no_sanitize("integer"))), -)
- DEFINE_C2_CNTR_UNARY_OP(__attribute__((no_sanitize("integer"))), +)
+ DEFINE_C2_CNTR_UNARY_OP(C2_ALLOW_OVERFLOW, -)
+ DEFINE_C2_CNTR_UNARY_OP(C2_ALLOW_OVERFLOW, +)
- DEFINE_C2_CNTR_CREMENT_OP(__attribute__((no_sanitize("integer"))), ++)
- DEFINE_C2_CNTR_CREMENT_OP(__attribute__((no_sanitize("integer"))), --)
+ DEFINE_C2_CNTR_CREMENT_OP(C2_ALLOW_OVERFLOW, ++)
+ DEFINE_C2_CNTR_CREMENT_OP(C2_ALLOW_OVERFLOW, --)
template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type>
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline constexpr c2_cntr_t<T> operator<<(const U &value) const {
return c2_cntr_t<T>(mValue << value);
}
template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type>
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline c2_cntr_t<T> &operator<<=(const U &value) {
mValue <<= value;
return *this;
@@ -378,12 +379,12 @@
/**
* Comparison operators
*/
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline constexpr bool operator<=(const c2_cntr_t<T> &other) const {
return T(other.mValue - mValue) < HALF_RANGE;
}
- __attribute__((no_sanitize("integer")))
+ C2_ALLOW_OVERFLOW
inline constexpr bool operator>=(const c2_cntr_t<T> &other) const {
return T(mValue - other.mValue) < HALF_RANGE;
}
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 2ca8222..45ad17f 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -126,9 +126,16 @@
*/
bool isHW() const;
+ /**
+ * Null-fence. A fence that has fired.
+ */
+ constexpr C2Fence() : mImpl(nullptr) { }
+
private:
class Impl;
std::shared_ptr<Impl> mImpl;
+ C2Fence(const std::shared_ptr<Impl> &impl);
+ friend struct _C2FenceFactory;
};
/**
@@ -245,13 +252,101 @@
**************************************************************************************************/
/**
+ * Basic segment math support.
+ */
+struct C2Segment {
+ uint32_t offset;
+ uint32_t size;
+
+ inline constexpr C2Segment(uint32_t offset_, uint32_t size_)
+ : offset(offset_),
+ size(size_) {
+ }
+
+ inline constexpr bool isEmpty() const {
+ return size == 0;
+ }
+
+ inline constexpr bool isValid() const {
+ return offset <= ~size;
+ }
+
+ inline constexpr operator bool() const {
+ return isValid() && !isEmpty();
+ }
+
+ inline constexpr bool operator!() const {
+ return !bool(*this);
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr bool contains(const C2Segment &other) const {
+ if (!isValid() || !other.isValid()) {
+ return false;
+ } else {
+ return offset <= other.offset
+ && offset + size >= other.offset + other.size;
+ }
+ }
+
+ inline constexpr bool operator==(const C2Segment &other) const {
+ if (!isValid()) {
+ return !other.isValid();
+ } else {
+ return offset == other.offset && size == other.size;
+ }
+ }
+
+ inline constexpr bool operator!=(const C2Segment &other) const {
+ return !operator==(other);
+ }
+
+ inline constexpr bool operator>=(const C2Segment &other) const {
+ return contains(other);
+ }
+
+ inline constexpr bool operator>(const C2Segment &other) const {
+ return contains(other) && !operator==(other);
+ }
+
+ inline constexpr bool operator<=(const C2Segment &other) const {
+ return other.contains(*this);
+ }
+
+ inline constexpr bool operator<(const C2Segment &other) const {
+ return other.contains(*this) && !operator==(other);
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr uint32_t end() const {
+ return offset + size;
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr C2Segment intersect(const C2Segment &other) const {
+ if (!isValid()) {
+ return *this;
+ } else if (!other.isValid()) {
+ return other;
+ } else {
+ return C2Segment(c2_max(offset, other.offset),
+ c2_min(end(), other.end()) - c2_max(offset, other.offset));
+ }
+ }
+};
+
+/**
* Common aspect for all objects that have a linear capacity.
*/
class _C2LinearCapacityAspect {
/// \name Linear capacity interface
/// @{
public:
- inline uint32_t capacity() const { return mCapacity; }
+ inline constexpr uint32_t capacity() const { return mCapacity; }
+
+ inline constexpr operator C2Segment() const {
+ return C2Segment(0, mCapacity);
+ }
protected:
@@ -263,10 +358,10 @@
inline explicit _C2LinearCapacityAspect(size_t capacity) = delete;
#endif
- inline explicit _C2LinearCapacityAspect(uint32_t capacity)
+ inline explicit constexpr _C2LinearCapacityAspect(uint32_t capacity)
: mCapacity(capacity) { }
- inline explicit _C2LinearCapacityAspect(const _C2LinearCapacityAspect *parent)
+ inline explicit constexpr _C2LinearCapacityAspect(const _C2LinearCapacityAspect *parent)
: mCapacity(parent == nullptr ? 0 : parent->capacity()) { }
private:
@@ -283,23 +378,35 @@
/// \name Linear range interface
/// @{
public:
- inline uint32_t offset() const { return mOffset; }
- inline uint32_t endOffset() const { return mOffset + mSize; }
- inline uint32_t size() const { return mSize; }
+ inline constexpr uint32_t offset() const { return mOffset; }
+ inline constexpr uint32_t endOffset() const { return mOffset + mSize; }
+ inline constexpr uint32_t size() const { return mSize; }
+
+ inline constexpr operator C2Segment() const {
+ return C2Segment(mOffset, mSize);
+ }
protected:
- inline explicit _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent)
+ // capacity range [0, capacity]
+ inline constexpr explicit _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent)
: _C2LinearCapacityAspect(parent),
mOffset(0),
mSize(capacity()) { }
- inline _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent, size_t offset, size_t size)
+ // copy constructor (no error check)
+ inline constexpr _C2LinearRangeAspect(const _C2LinearRangeAspect &other)
+ : _C2LinearCapacityAspect(other.capacity()),
+ mOffset(other.offset()),
+ mSize(other.size()) { }
+
+ // subrange of capacity [0, capacity] & [size, size + offset]
+ inline constexpr _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent, size_t offset, size_t size)
: _C2LinearCapacityAspect(parent),
mOffset(c2_min(offset, capacity())),
mSize(c2_min(size, capacity() - mOffset)) { }
// subsection of the two [offset, offset + size] ranges
- inline _C2LinearRangeAspect(const _C2LinearRangeAspect *parent, size_t offset, size_t size)
+ inline constexpr _C2LinearRangeAspect(const _C2LinearRangeAspect *parent, size_t offset, size_t size)
: _C2LinearCapacityAspect(parent == nullptr ? 0 : parent->capacity()),
mOffset(c2_min(c2_max(offset, parent == nullptr ? 0 : parent->offset()), capacity())),
mSize(c2_min(c2_min(size, parent == nullptr ? 0 : parent->size()), capacity() - mOffset)) { }
@@ -312,28 +419,31 @@
/// @}
};
-class C2_HIDE _C2LinearCapacityBase : public _C2LinearCapacityAspect {
-public:
- inline explicit _C2LinearCapacityBase(size_t capacity)
- : _C2LinearCapacityAspect(c2_min(capacity, std::numeric_limits<uint32_t>::max())) {}
-};
-
/**
* Utility class for safe range calculations.
*/
class C2LinearRange : public _C2LinearRangeAspect {
public:
- inline C2LinearRange(const _C2LinearCapacityBase &parent, size_t offset, size_t size)
- : _C2LinearRangeAspect(&parent, offset, size) {}
+ inline constexpr C2LinearRange(const _C2LinearCapacityAspect &parent, size_t offset, size_t size)
+ : _C2LinearRangeAspect(&parent, offset, size) { }
+
+ inline constexpr C2LinearRange(const _C2LinearRangeAspect &parent, size_t offset, size_t size)
+ : _C2LinearRangeAspect(&parent, offset, size) { }
+
+ inline constexpr C2LinearRange intersect(size_t offset, size_t size) const {
+ return C2LinearRange(*this, offset, size);
+ }
};
/**
* Utility class for simple capacity and range construction.
*/
-class C2LinearCapacity : public _C2LinearCapacityBase {
+class C2LinearCapacity : public _C2LinearCapacityAspect {
public:
- using _C2LinearCapacityBase::_C2LinearCapacityBase;
- inline C2LinearRange range(size_t offset, size_t size) {
+ inline constexpr explicit C2LinearCapacity(size_t capacity)
+ : _C2LinearCapacityAspect(c2_min(capacity, std::numeric_limits<uint32_t>::max())) { }
+
+ inline constexpr C2LinearRange range(size_t offset, size_t size) const {
return C2LinearRange(*this, offset, size);
}
};
@@ -348,6 +458,9 @@
inline explicit _C2EditableLinearRange(const _C2LinearCapacityAspect *parent)
: _C2LinearRangeAspect(parent) { }
+ inline _C2EditableLinearRange(const _C2LinearRangeAspect &other)
+ : _C2LinearRangeAspect(other) { }
+
inline _C2EditableLinearRange(const _C2LinearCapacityAspect *parent, size_t offset, size_t size)
: _C2LinearRangeAspect(parent, offset, size) { }
@@ -379,6 +492,7 @@
mOffset = offset;
return true;
}
+
/**
* Sets the size to |size|. Returns true if successful, which is equivalent to
* if 0 <= |size| <= capacity() - offset().
@@ -394,6 +508,7 @@
return true;
}
}
+
/**
* Sets the offset to |offset| with best effort. Same as setOffset() except that offset will
* be clamped to the buffer capacity.
@@ -402,16 +517,9 @@
* on the order of the operations. Always set offset first to ensure proper size.
*/
inline void setOffset_be(uint32_t offset) {
- if (offset > capacity()) {
- offset = capacity();
- }
- if (offset > mOffset + mSize) {
- mSize = 0;
- } else {
- mSize = mOffset + mSize - offset;
- }
- mOffset = offset;
+ (void)setOffset(c2_min(offset, capacity()));
}
+
/**
* Sets the size to |size| with best effort. Same as setSize() except that the selected region
* will be clamped to the buffer capacity (e.g. size is clamped to [0, capacity() - offset()]).
@@ -420,11 +528,471 @@
* on the order of the operations. Always set offset first to ensure proper size.
*/
inline void setSize_be(uint32_t size) {
- mSize = std::min(size, capacity() - mOffset);
+ mSize = c2_min(size, capacity() - mOffset);
}
/// @}
};
+/**************************************************************************************************
+ ALLOCATIONS
+**************************************************************************************************/
+
+/// \defgroup allocator Allocation and memory placement
+/// @{
+
+/**
+ * Buffer/memory usage bits. These are used by the allocators to select optimal memory type/pool and
+ * buffer layout.
+ *
+ * \note This struct has public fields without getters/setters. All methods are inline.
+ */
+struct C2MemoryUsage {
+// public:
+ // TODO: match these to gralloc1.h
+ enum Consumer : uint64_t {
+ // \todo do we need to distinguish often from rarely?
+ CPU_READ = GRALLOC_USAGE_SW_READ_OFTEN,
+ RENDERSCRIPT_READ = GRALLOC_USAGE_RENDERSCRIPT,
+ HW_TEXTURE_READ = GRALLOC_USAGE_HW_TEXTURE,
+ HW_COMPOSER_READ = GRALLOC_USAGE_HW_COMPOSER,
+ HW_CODEC_READ = GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ READ_PROTECTED = GRALLOC_USAGE_PROTECTED,
+ };
+
+ enum Producer : uint64_t {
+ CPU_WRITE = GRALLOC_USAGE_SW_WRITE_OFTEN,
+ RENDERSCRIPT_WRITE = GRALLOC_USAGE_RENDERSCRIPT,
+ HW_TEXTURE_WRITE = GRALLOC_USAGE_HW_RENDER,
+ HW_COMPOSER_WRITE = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER,
+ HW_CODEC_WRITE = GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ WRITE_PROTECTED = GRALLOC_USAGE_PROTECTED,
+ };
+
+ uint64_t consumer; // e.g. input
+ uint64_t producer; // e.g. output
+};
+
+class C2LinearAllocation;
+class C2GraphicAllocation;
+
+/**
+ * Allocators are used by the framework to allocate memory (allocations) for buffers. They can
+ * support either 1D or 2D allocations.
+ *
+ * \note In theory they could support both, but in practice, we will use only one or the other.
+ *
+ * Never constructed on stack.
+ *
+ * Allocators are provided by vendors.
+ */
+class C2Allocator {
+public:
+ /**
+ * Allocator ID type.
+ */
+ typedef uint32_t id_t;
+ enum : id_t {
+ BAD_ID = 0xBADD, // invalid allocator ID
+ };
+
+ /**
+ * Allocation types. This is a bitmask and is used in C2Allocator::Info
+ * to list the supported allocation types of an allocator.
+ */
+ enum type_t : uint32_t {
+ LINEAR = 1 << 0, //
+ GRAPHIC = 1 << 1,
+ };
+
+ /**
+ * Information about an allocator.
+ *
+ * Allocators don't have a query API so all queriable information is stored here.
+ */
+ struct Traits {
+ C2String name; ///< allocator name
+ id_t id; ///< allocator ID
+ type_t supportedTypes; ///< supported allocation types
+ C2MemoryUsage minimumUsage; ///< usage that is minimally required for allocations
+ C2MemoryUsage maximumUsage; ///< usage that is maximally allowed for allocations
+ };
+
+ /**
+ * Returns the unique name of this allocator.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this allocator.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Returns a unique ID for this allocator. This ID is used to get this allocator from the
+ * allocator store, and to identify this allocator across all processes.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a unique ID for this allocator.
+ */
+ virtual id_t getId() const = 0;
+
+ /**
+ * Returns the allocator traits.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * Allocators don't have a full-fledged query API, only this method.
+ *
+ * \return allocator information
+ */
+ virtual std::shared_ptr<const Traits> getTraits() const = 0;
+
+ /**
+ * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
+ * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param usage the memory usage info for the requested allocation. \note that the
+ * returned allocation may be later used/mapped with different usage.
+ * The allocator should layout the buffer to be optimized for this usage,
+ * but must support any usage. One exception: protected buffers can
+ * only be used in a protected scenario.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete the allocation
+ * \retval C2_TIMED_OUT the allocation timed out
+ * \retval C2_REFUSED no permission to complete the allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this allocator does not support 1D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+ virtual c2_status_t newLinearAllocation(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored
+ * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param handle the handle for the existing allocation
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was recreated successfully
+ * \retval C2_NO_MEMORY not enough memory to recreate the allocation
+ * \retval C2_TIMED_OUT the recreation timed out (unexpected)
+ * \retval C2_REFUSED no permission to recreate the allocation
+ * \retval C2_BAD_VALUE invalid handle (caller error)
+ * \retval C2_OMITTED this allocator does not support 1D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+ virtual c2_status_t priorLinearAllocation(
+ const C2Handle *handle __unused,
+ std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful,
+ * the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param width the width of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param height the height of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param format the pixel format of requested allocation. This could be a vendor
+ * specific format.
+ * \param usage the memory usage info for the requested allocation. \note that the
+ * returned allocation may be later used/mapped with different usage.
+ * The allocator should layout the buffer to be optimized for this usage,
+ * but must support any usage. One exception: protected buffers can
+ * only be used in a protected scenario.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete the allocation
+ * \retval C2_TIMED_OUT the allocation timed out
+ * \retval C2_REFUSED no permission to complete the allocation
+ * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this allocator does not support 2D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+ virtual c2_status_t newGraphicAllocation(
+ uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
+ C2MemoryUsage usage __unused,
+ std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * (Re)creates a 2D allocation from a native handle. If successful, the allocation is stored
+ * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param handle the handle for the existing allocation
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was recreated successfully
+ * \retval C2_NO_MEMORY not enough memory to recreate the allocation
+ * \retval C2_TIMED_OUT the recreation timed out (unexpected)
+ * \retval C2_REFUSED no permission to recreate the allocation
+ * \retval C2_BAD_VALUE invalid handle (caller error)
+ * \retval C2_OMITTED this allocator does not support 2D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
+ */
+ virtual c2_status_t priorGraphicAllocation(
+ const C2Handle *handle __unused,
+ std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+protected:
+ C2Allocator() = default;
+
+ virtual ~C2Allocator() = default;
+};
+
+/**
+ * \ingroup linear allocator
+ * 1D allocation interface.
+ */
+class C2LinearAllocation : public _C2LinearCapacityAspect {
+public:
+ /**
+ * Maps a portion of an allocation starting from |offset| with |size| into local process memory.
+ * Stores the starting address into |addr|, or NULL if the operation was unsuccessful.
+ * |fenceFd| is a file descriptor referring to an acquire sync fence object. If it is already
+ * safe to access the buffer contents, then -1.
+ *
+ * \param offset starting position of the portion to be mapped (this does not have to
+ * be page aligned)
+ * \param size size of the portion to be mapped (this does not have to be page
+ * aligned)
+ * \param usage the desired usage. \todo this must be kSoftwareRead and/or
+ * kSoftwareWrite.
+ * \param fenceFd a pointer to a file descriptor if an async mapping is requested. If
+ * not-null, and acquire fence FD will be stored here on success, or -1
+ * on failure. If null, the mapping will be synchronous.
+ * \param addr a pointer to where the starting address of the mapped portion will be
+ * stored. On failure, nullptr will be stored here.
+ *
+ * \todo Only one portion can be mapped at the same time - this is true for gralloc, but there
+ * is no need for this for 1D buffers.
+ * \todo Do we need to support sync operation as we could just wait for the fence?
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_REFUSED no permission to map the portion
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_DUPLICATE if the allocation is already mapped.
+ * \retval C2_NO_MEMORY not enough memory to complete the operation
+ * \retval C2_BAD_VALUE the parameters (offset/size) are invalid or outside the allocation, or
+ * the usage flags are invalid (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ */
+ virtual c2_status_t map(
+ size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
+ void **addr /* nonnull */) = 0;
+
+ /**
+ * Unmaps a portion of an allocation at |addr| with |size|. These must be parameters previously
+ * passed to |map|; otherwise, this operation is a no-op.
+ *
+ * \param addr starting address of the mapped region
+ * \param size size of the mapped region
+ * \param fenceFd a pointer to a file descriptor if an async unmapping is requested. If
+ * not-null, a release fence FD will be stored here on success, or -1
+ * on failure. This fence signals when the original allocation contains
+ * any changes that happened to the mapped region. If null, the unmapping
+ * will be synchronous.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_NOT_FOUND if the allocation was not mapped previously.
+ * \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped
+ * regions (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ * \retval C2_REFUSED no permission to unmap the portion (unexpected - system)
+ */
+ virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+
+ /**
+ * Returns the allocator ID for this allocation. This is useful to put the handle into context.
+ */
+ virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+ /**
+ * Returns a pointer to the allocation handle.
+ */
+ virtual const C2Handle *handle() const = 0;
+
+ /**
+ * Returns true if this is the same allocation as |other|.
+ */
+ virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const = 0;
+
+protected:
+ // \todo should we limit allocation directly?
+ C2LinearAllocation(size_t capacity) : _C2LinearCapacityAspect(c2_min(capacity, UINT32_MAX)) {}
+ virtual ~C2LinearAllocation() = default;
+};
+
+class C2CircularBlock;
+class C2LinearBlock;
+class C2GraphicBlock;
+
+/**
+ * Block pools are used by components to obtain output buffers in an efficient way. They can
+ * support either linear (1D), circular (1D) or graphic (2D) blocks.
+ *
+ * Block pools decouple the recycling of memory/allocations from the components. They are meant to
+ * be an opaque service (there are no public APIs other than obtaining blocks) provided by the
+ * platform. Block pools are also meant to decouple allocations from memory used by buffers. This
+ * is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As
+ * their name suggest, block pools maintain a pool of memory blocks. When a component asks for
+ * a memory block, pools will try to return a free memory block already in the pool. If no such
+ * block exists, they will allocate memory using the backing allocator and allot a block on that
+ * allocation. When blocks are no longer used in the system, they are recycled back to the block
+ * pool and are available as free blocks.
+ *
+ * Never constructed on stack.
+ */
+class C2BlockPool {
+public:
+ /**
+ * Block pool ID type.
+ */
+ typedef uint64_t local_id_t;
+
+ enum : local_id_t {
+ BASIC_LINEAR = 0, ///< ID of basic (unoptimized) block pool for fetching 1D blocks
+ BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks
+ PLATFORM_START = 0x10,
+ };
+
+ /**
+ * Returns the ID for this block pool. This ID is used to get this block pool from the platform.
+ * It is only valid in the current process.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a local ID for this block pool.
+ */
+ virtual local_id_t getLocalId() const = 0;
+
+ /**
+ * Returns the ID of the backing allocator of this block pool.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the ID of the backing allocator of this block pool.
+ */
+ virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+ /**
+ * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the
+ * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested block.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr will
+ * be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this pool does not support linear blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ */
+ virtual c2_status_t fetchLinearBlock(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+ *block = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the
+ * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested circular block. (note: the size of the obtained
+ * block could be slightly larger, e.g. to accommodate any system-required
+ * alignment)
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this pool does not support circular blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ */
+ virtual c2_status_t fetchCircularBlock(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
+ *block = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
+ * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ *
+ * \param width the width of requested block (the obtained block could be slightly larger, e.g.
+ * to accommodate any system-required alignment)
+ * \param height the height of requested block (the obtained block could be slightly larger,
+ * e.g. to accommodate any system-required alignment)
+ * \param format the pixel format of requested block. This could be a vendor specific format.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
+ * error)
+ * \retval C2_OMITTED this pool does not support 2D blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ */
+ virtual c2_status_t fetchGraphicBlock(
+ uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
+ C2MemoryUsage usage __unused,
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
+ *block = nullptr;
+ return C2_OMITTED;
+ }
+
+protected:
+ C2BlockPool() = default;
+
+ virtual ~C2BlockPool() = default;
+};
+
+/// @}
+
// ================================================================================================
// BLOCKS
// ================================================================================================
@@ -435,16 +1003,36 @@
class C2LinearAllocation;
+/**
+ * A 1D block.
+ *
+ * \note capacity() is not meaningful for users of blocks; instead size() is the capacity of the
+ * usable portion. Use and offset() and size() if accessing the block directly through its handle
+ * to represent the allotted range of the underlying allocation to this block.
+ */
class C2Block1D : public _C2LinearRangeAspect {
public:
+ /**
+ * Returns the underlying handle for this allocation.
+ *
+ * \note that the block and its block pool has shared ownership of the handle
+ * and if all references to the block are released, the underlying block
+ * allocation may get reused even if a client keeps a clone of this handle.
+ */
const C2Handle *handle() const;
-protected:
- C2Block1D(std::shared_ptr<C2LinearAllocation> alloc);
- C2Block1D(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size);
+ /**
+ * Returns the allocator's ID that created the underlying allocation for this block. This
+ * provides the context for understanding the handle.
+ */
+ C2Allocator::id_t getAllocatorId() const;
-private:
+protected:
class Impl;
+ /** construct a block. */
+ C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range);
+
+ friend struct _C2BlockFactory;
std::shared_ptr<Impl> mImpl;
};
@@ -457,6 +1045,7 @@
public:
/**
* \return pointer to the start of the block or nullptr on error.
+ * This pointer is only valid during the lifetime of this view or until it is released.
*/
const uint8_t *data() const;
@@ -476,13 +1065,20 @@
*/
c2_status_t error() const;
+ /**
+ * Releases this view. This sets error to C2_NO_INIT.
+ */
+ //void release();
+
protected:
- C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
+ class Impl;
+ C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size);
explicit C2ReadView(c2_status_t error);
private:
- class Impl;
+ friend struct _C2BlockFactory;
std::shared_ptr<Impl> mImpl;
+ uint32_t mOffset; /**< offset into the linear block backing this read view */
};
/**
@@ -496,11 +1092,13 @@
* Start of the block.
*
* \return pointer to the start of the block or nullptr on error.
+ * This pointer is only valid during the lifetime of this view or until it is released.
*/
uint8_t *base();
/**
* \return pointer to the block at the current offset or nullptr on error.
+ * This pointer is only valid during the lifetime of this view or until it is released.
*/
uint8_t *data();
@@ -509,14 +1107,18 @@
*/
c2_status_t error() const;
+ /**
+ * Releases this view. This sets error to C2_NO_INIT.
+ */
+ //void release();
+
protected:
- C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
+ class Impl;
+ C2WriteView(std::shared_ptr<Impl> impl);
explicit C2WriteView(c2_status_t error);
private:
- class Impl;
- /// \todo should this be unique_ptr to make this movable only - to avoid inconsistent regions
- /// between copies.
+ friend struct _C2BlockFactory;
std::shared_ptr<Impl> mImpl;
};
@@ -554,12 +1156,10 @@
C2Fence fence() const { return mFence; }
protected:
- C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc);
- C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size);
+ C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence mFence);
private:
- class Impl;
- std::shared_ptr<Impl> mImpl;
+ friend struct _C2BlockFactory;
C2Fence mFence;
};
@@ -589,12 +1189,9 @@
C2ConstLinearBlock share(size_t offset, size_t size, C2Fence fence);
protected:
- C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc);
- C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size);
+ C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range);
-private:
- class Impl;
- std::shared_ptr<Impl> mImpl;
+ friend struct _C2BlockFactory;
};
/// @}
@@ -800,27 +1397,26 @@
// utility methods
- inline bool isEmpty() const {
+ inline constexpr bool isEmpty() const {
return width == 0 || height == 0;
}
- inline bool isValid() const {
+ inline constexpr bool isValid() const {
return left <= ~width && top <= ~height;
}
- inline operator bool() const {
+ inline constexpr operator bool() const {
return isValid() && !isEmpty();
}
- inline bool operator!() const {
+ inline constexpr bool operator!() const {
return !bool(*this);
}
- inline bool contains(const C2Rect &other) const {
+ C2_ALLOW_OVERFLOW
+ inline constexpr bool contains(const C2Rect &other) const {
if (!isValid() || !other.isValid()) {
return false;
- } else if (other.isEmpty()) {
- return true;
} else {
return left <= other.left && top <= other.top
&& left + width >= other.left + other.width
@@ -828,36 +1424,58 @@
}
}
- inline bool operator==(const C2Rect &other) const {
+ inline constexpr bool operator==(const C2Rect &other) const {
if (!isValid()) {
return !other.isValid();
- } else if (isEmpty()) {
- return other.isEmpty();
} else {
return left == other.left && top == other.top
&& width == other.width && height == other.height;
}
}
- inline bool operator!=(const C2Rect &other) const {
+ inline constexpr bool operator!=(const C2Rect &other) const {
return !operator==(other);
}
- inline bool operator>=(const C2Rect &other) const {
+ inline constexpr bool operator>=(const C2Rect &other) const {
return contains(other);
}
- inline bool operator>(const C2Rect &other) const {
+ inline constexpr bool operator>(const C2Rect &other) const {
return contains(other) && !operator==(other);
}
- inline bool operator<=(const C2Rect &other) const {
+ inline constexpr bool operator<=(const C2Rect &other) const {
return other.contains(*this);
}
- inline bool operator<(const C2Rect &other) const {
+ inline constexpr bool operator<(const C2Rect &other) const {
return other.contains(*this) && !operator==(other);
}
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr uint32_t right() const {
+ return left + width;
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr uint32_t bottom() const {
+ return top + height;
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr C2Rect intersect(const C2Rect &other) const {
+ if (!isValid()) {
+ return *this;
+ } else if (!other.isValid()) {
+ return other;
+ } else {
+ return C2Rect(c2_min(right(), other.right()) - c2_max(left, other.left),
+ c2_min(bottom(), other.bottom()) - c2_max(top, other.top),
+ c2_max(left, other.left),
+ c2_max(top, other.top));
+ }
+ }
};
/**
@@ -1008,6 +1626,88 @@
/// @}
};
+/**
+ * \ingroup graphic allocator
+ * 2D allocation interface.
+ */
+class C2GraphicAllocation : public _C2PlanarCapacityAspect {
+public:
+ /**
+ * Maps a rectangular section (as defined by |rect|) of a 2D allocation into local process
+ * memory for flexible access. On success, it fills out |layout| with the plane specifications
+ * and fills the |addr| array with pointers to the first byte of the top-left pixel of each
+ * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fenceFd| is a file
+ * descriptor referring to an acquire sync fence object. If it is already safe to access the
+ * buffer contents, then -1.
+ *
+ * \note Only one portion of the graphic allocation can be mapped at the same time. (This is
+ * from gralloc1 limitation.)
+ *
+ * \param rect section to be mapped (this does not have to be aligned)
+ * \param usage the desired usage. \todo this must be kSoftwareRead and/or
+ * kSoftwareWrite.
+ * \param fenceFd a pointer to a file descriptor if an async mapping is requested. If
+ * not-null, and acquire fence FD will be stored here on success, or -1
+ * on failure. If null, the mapping will be synchronous.
+ * \param layout a pointer to where the mapped planes' descriptors will be
+ * stored. On failure, nullptr will be stored here.
+ *
+ * \todo Do we need to support sync operation as we could just wait for the fence?
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_REFUSED no permission to map the section
+ * \retval C2_DUPLICATE there is already a mapped region (caller error)
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_NO_MEMORY not enough memory to complete the operation
+ * \retval C2_BAD_VALUE the parameters (rect) are invalid or outside the allocation, or the
+ * usage flags are invalid (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+
+ */
+ virtual c2_status_t map(
+ C2Rect rect, C2MemoryUsage usage, int *fenceFd,
+ // TODO: return <addr, size> buffers with plane sizes
+ C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
+
+ /**
+ * Unmaps the last mapped rectangular section.
+ *
+ * \param fenceFd a pointer to a file descriptor if an async unmapping is requested. If
+ * not-null, a release fence FD will be stored here on success, or -1
+ * on failure. This fence signals when the original allocation contains
+ * any changes that happened to the mapped section. If null, the unmapping
+ * will be synchronous.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_NOT_FOUND there is no mapped region (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ * \retval C2_REFUSED no permission to unmap the section (unexpected - system)
+ */
+ virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) = 0;
+
+ /**
+ * Returns true if this is a valid allocation.
+ *
+ * \todo remove?
+ */
+ virtual bool isValid() const = 0;
+
+ /**
+ * Returns a pointer to the allocation handle.
+ */
+ virtual const C2Handle *handle() const = 0;
+
+ /**
+ * Returns true if this is the same allocation as |other|.
+ */
+ virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const = 0;
+
+protected:
+ using _C2PlanarCapacityAspect::_C2PlanarCapacityAspect;
+ virtual ~C2GraphicAllocation() = default;
+};
+
class C2GraphicAllocation;
class C2Block2D : public _C2PlanarSection {
@@ -1323,9 +2023,33 @@
* \return true iff there is a metadata with the parameter type attached to this buffer.
*/
bool hasInfo(C2Param::Type index) const;
+
+ /**
+ * Removes a metadata from the buffer.
+ */
std::shared_ptr<C2Info> removeInfo(C2Param::Type index);
///@}
+ /**
+ * Creates a buffer containing a single linear block.
+ *
+ * \param block the content of the buffer.
+ *
+ * \return shared pointer to the created buffer.
+ */
+ static std::shared_ptr<C2Buffer> CreateLinearBuffer(const C2ConstLinearBlock &block);
+
+ /**
+ * Creates a buffer containing a single graphic block.
+ *
+ * \param block the content of the buffer.
+ *
+ * \return shared pointer to the created buffer.
+ */
+ static std::shared_ptr<C2Buffer> CreateGraphicBuffer(const C2ConstGraphicBlock &block);
+
+
+
protected:
// no public constructor
explicit C2Buffer(const std::vector<C2ConstLinearBlock> &blocks);
@@ -1361,540 +2085,6 @@
/// @}
-/**************************************************************************************************
- ALLOCATIONS
-**************************************************************************************************/
-
-/// \defgroup allocator Allocation and memory placement
-/// @{
-
-/**
- * Buffer/memory usage bits. These are used by the allocators to select optimal memory type/pool and
- * buffer layout.
- *
- * \note This struct has public fields without getters/setters. All methods are inline.
- */
-struct C2MemoryUsage {
-// public:
- // TODO: match these to gralloc1.h
- enum Consumer : uint64_t {
- // \todo do we need to distinguish often from rarely?
- CPU_READ = GRALLOC_USAGE_SW_READ_OFTEN,
- RENDERSCRIPT_READ = GRALLOC_USAGE_RENDERSCRIPT,
- HW_TEXTURE_READ = GRALLOC_USAGE_HW_TEXTURE,
- HW_COMPOSER_READ = GRALLOC_USAGE_HW_COMPOSER,
- HW_CODEC_READ = GRALLOC_USAGE_HW_VIDEO_ENCODER,
- READ_PROTECTED = GRALLOC_USAGE_PROTECTED,
- };
-
- enum Producer : uint64_t {
- CPU_WRITE = GRALLOC_USAGE_SW_WRITE_OFTEN,
- RENDERSCRIPT_WRITE = GRALLOC_USAGE_RENDERSCRIPT,
- HW_TEXTURE_WRITE = GRALLOC_USAGE_HW_RENDER,
- HW_COMPOSER_WRITE = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER,
- HW_CODEC_WRITE = GRALLOC_USAGE_HW_VIDEO_ENCODER,
- WRITE_PROTECTED = GRALLOC_USAGE_PROTECTED,
- };
-
- uint64_t consumer; // e.g. input
- uint64_t producer; // e.g. output
-};
-
-/**
- * \ingroup linear allocator
- * 1D allocation interface.
- */
-class C2LinearAllocation : public _C2LinearCapacityAspect {
-public:
- /**
- * Maps a portion of an allocation starting from |offset| with |size| into local process memory.
- * Stores the starting address into |addr|, or NULL if the operation was unsuccessful.
- * |fenceFd| is a file descriptor referring to an acquire sync fence object. If it is already
- * safe to access the buffer contents, then -1.
- *
- * \param offset starting position of the portion to be mapped (this does not have to
- * be page aligned)
- * \param size size of the portion to be mapped (this does not have to be page
- * aligned)
- * \param usage the desired usage. \todo this must be kSoftwareRead and/or
- * kSoftwareWrite.
- * \param fenceFd a pointer to a file descriptor if an async mapping is requested. If
- * not-null, and acquire fence FD will be stored here on success, or -1
- * on failure. If null, the mapping will be synchronous.
- * \param addr a pointer to where the starting address of the mapped portion will be
- * stored. On failure, nullptr will be stored here.
- *
- * \todo Only one portion can be mapped at the same time - this is true for gralloc, but there
- * is no need for this for 1D buffers.
- * \todo Do we need to support sync operation as we could just wait for the fence?
- *
- * \retval C2_OK the operation was successful
- * \retval C2_REFUSED no permission to map the portion
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_DUPLICATE if the allocation is already mapped.
- * \retval C2_NO_MEMORY not enough memory to complete the operation
- * \retval C2_BAD_VALUE the parameters (offset/size) are invalid or outside the allocation, or
- * the usage flags are invalid (caller error)
- * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- */
- virtual c2_status_t map(
- size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
- void **addr /* nonnull */) = 0;
-
- /**
- * Unmaps a portion of an allocation at |addr| with |size|. These must be parameters previously
- * passed to |map|; otherwise, this operation is a no-op.
- *
- * \param addr starting address of the mapped region
- * \param size size of the mapped region
- * \param fenceFd a pointer to a file descriptor if an async unmapping is requested. If
- * not-null, a release fence FD will be stored here on success, or -1
- * on failure. This fence signals when the original allocation contains
- * any changes that happened to the mapped region. If null, the unmapping
- * will be synchronous.
- *
- * \retval C2_OK the operation was successful
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_NOT_FOUND if the allocation was not mapped previously.
- * \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped
- * regions (caller error)
- * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- * \retval C2_REFUSED no permission to unmap the portion (unexpected - system)
- */
- virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
-
- /**
- * Returns true if this is a valid allocation.
- *
- * \todo remove?
- */
- virtual bool isValid() const = 0;
-
- /**
- * Returns a pointer to the allocation handle.
- */
- virtual const C2Handle *handle() const = 0;
-
- /**
- * Returns true if this is the same allocation as |other|.
- */
- virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const = 0;
-
-protected:
- // \todo should we limit allocation directly?
- C2LinearAllocation(size_t capacity) : _C2LinearCapacityAspect(c2_min(capacity, UINT32_MAX)) {}
- virtual ~C2LinearAllocation() = default;
-};
-
-/**
- * \ingroup graphic allocator
- * 2D allocation interface.
- */
-class C2GraphicAllocation : public _C2PlanarCapacityAspect {
-public:
- /**
- * Maps a rectangular section (as defined by |rect|) of a 2D allocation into local process
- * memory for flexible access. On success, it fills out |layout| with the plane specifications
- * and fills the |addr| array with pointers to the first byte of the top-left pixel of each
- * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fenceFd| is a file
- * descriptor referring to an acquire sync fence object. If it is already safe to access the
- * buffer contents, then -1.
- *
- * \note Only one portion of the graphic allocation can be mapped at the same time. (This is
- * from gralloc1 limitation.)
- *
- * \param rect section to be mapped (this does not have to be aligned)
- * \param usage the desired usage. \todo this must be kSoftwareRead and/or
- * kSoftwareWrite.
- * \param fenceFd a pointer to a file descriptor if an async mapping is requested. If
- * not-null, and acquire fence FD will be stored here on success, or -1
- * on failure. If null, the mapping will be synchronous.
- * \param layout a pointer to where the mapped planes' descriptors will be
- * stored. On failure, nullptr will be stored here.
- *
- * \todo Do we need to support sync operation as we could just wait for the fence?
- *
- * \retval C2_OK the operation was successful
- * \retval C2_REFUSED no permission to map the section
- * \retval C2_DUPLICATE there is already a mapped region (caller error)
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_NO_MEMORY not enough memory to complete the operation
- * \retval C2_BAD_VALUE the parameters (rect) are invalid or outside the allocation, or the
- * usage flags are invalid (caller error)
- * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
-
- */
- virtual c2_status_t map(
- C2Rect rect, C2MemoryUsage usage, int *fenceFd,
- // TODO: return <addr, size> buffers with plane sizes
- C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
-
- /**
- * Unmaps the last mapped rectangular section.
- *
- * \param fenceFd a pointer to a file descriptor if an async unmapping is requested. If
- * not-null, a release fence FD will be stored here on success, or -1
- * on failure. This fence signals when the original allocation contains
- * any changes that happened to the mapped section. If null, the unmapping
- * will be synchronous.
- *
- * \retval C2_OK the operation was successful
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_NOT_FOUND there is no mapped region (caller error)
- * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- * \retval C2_REFUSED no permission to unmap the section (unexpected - system)
- */
- virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) = 0;
-
- /**
- * Returns true if this is a valid allocation.
- *
- * \todo remove?
- */
- virtual bool isValid() const = 0;
-
- /**
- * Returns a pointer to the allocation handle.
- */
- virtual const C2Handle *handle() const = 0;
-
- /**
- * Returns true if this is the same allocation as |other|.
- */
- virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const = 0;
-
-protected:
- using _C2PlanarCapacityAspect::_C2PlanarCapacityAspect;
- virtual ~C2GraphicAllocation() = default;
-};
-
-/**
- * Allocators are used by the framework to allocate memory (allocations) for buffers. They can
- * support either 1D or 2D allocations.
- *
- * \note In theory they could support both, but in practice, we will use only one or the other.
- *
- * Never constructed on stack.
- *
- * Allocators are provided by vendors.
- */
-class C2Allocator {
-public:
- /**
- * Allocator ID type.
- */
- typedef uint32_t id_t;
-
- /**
- * Allocation types. This is a bitmask and is used in C2Allocator::Info
- * to list the supported allocation types of an allocator.
- */
- enum type_t : uint32_t {
- LINEAR = 1 << 0, //
- GRAPHIC = 1 << 1,
- };
-
- /**
- * Information about an allocator.
- *
- * Allocators don't have a query API so all queriable information is stored here.
- */
- struct Traits {
- C2String name; ///< allocator name
- id_t id; ///< allocator ID
- type_t supportedTypes; ///< supported allocation types
- C2MemoryUsage minimumUsage; ///< usage that is minimally required for allocations
- C2MemoryUsage maximumUsage; ///< usage that is maximally allowed for allocations
- };
-
- /**
- * Returns the unique name of this allocator.
- *
- * This method MUST be "non-blocking" and return within 1ms.
- *
- * \return the name of this allocator.
- * \retval an empty string if there was not enough memory to allocate the actual name.
- */
- virtual C2String getName() const = 0;
-
- /**
- * Returns a unique ID for this allocator. This ID is used to get this allocator from the
- * allocator store, and to identify this allocator across all processes.
- *
- * This method MUST be "non-blocking" and return within 1ms.
- *
- * \return a unique ID for this allocator.
- */
- virtual id_t getId() const = 0;
-
- /**
- * Returns the allocator traits.
- *
- * This method MUST be "non-blocking" and return within 1ms.
- *
- * Allocators don't have a full-fledged query API, only this method.
- *
- * \return allocator information
- */
- virtual std::shared_ptr<const Traits> getTraits() const = 0;
-
- /**
- * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
- * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
- *
- * \param capacity the size of requested allocation (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param usage the memory usage info for the requested allocation. \note that the
- * returned allocation may be later used/mapped with different usage.
- * The allocator should layout the buffer to be optimized for this usage,
- * but must support any usage. One exception: protected buffers can
- * only be used in a protected scenario.
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the allocation was successful
- * \retval C2_NO_MEMORY not enough memory to complete the allocation
- * \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_REFUSED no permission to complete the allocation
- * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this allocator does not support 1D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
- */
- virtual c2_status_t newLinearAllocation(
- uint32_t capacity __unused, C2MemoryUsage usage __unused,
- std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
- *allocation = nullptr;
- return C2_OMITTED;
- }
-
- /**
- * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored
- * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
- *
- * \param handle the handle for the existing allocation
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the allocation was recreated successfully
- * \retval C2_NO_MEMORY not enough memory to recreate the allocation
- * \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_REFUSED no permission to recreate the allocation
- * \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_OMITTED this allocator does not support 1D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
- */
- virtual c2_status_t priorLinearAllocation(
- const C2Handle *handle __unused,
- std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
- *allocation = nullptr;
- return C2_OMITTED;
- }
-
- /**
- * Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful,
- * the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
- *
- * \param width the width of requested allocation (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param height the height of requested allocation (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param format the pixel format of requested allocation. This could be a vendor
- * specific format.
- * \param usage the memory usage info for the requested allocation. \note that the
- * returned allocation may be later used/mapped with different usage.
- * The allocator should layout the buffer to be optimized for this usage,
- * but must support any usage. One exception: protected buffers can
- * only be used in a protected scenario.
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the allocation was successful
- * \retval C2_NO_MEMORY not enough memory to complete the allocation
- * \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_REFUSED no permission to complete the allocation
- * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this allocator does not support 2D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
- */
- virtual c2_status_t newGraphicAllocation(
- uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
- C2MemoryUsage usage __unused,
- std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
- *allocation = nullptr;
- return C2_OMITTED;
- }
-
- /**
- * (Re)creates a 2D allocation from a native handle. If successful, the allocation is stored
- * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
- *
- * \param handle the handle for the existing allocation
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the allocation was recreated successfully
- * \retval C2_NO_MEMORY not enough memory to recreate the allocation
- * \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_REFUSED no permission to recreate the allocation
- * \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_OMITTED this allocator does not support 2D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
- */
- virtual c2_status_t priorGraphicAllocation(
- const C2Handle *handle __unused,
- std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
- *allocation = nullptr;
- return C2_OMITTED;
- }
-
-protected:
- C2Allocator() = default;
-
- virtual ~C2Allocator() = default;
-};
-
-/**
- * Block pools are used by components to obtain output buffers in an efficient way. They can
- * support either linear (1D), circular (1D) or graphic (2D) blocks.
- *
- * Block pools decouple the recycling of memory/allocations from the components. They are meant to
- * be an opaque service (there are no public APIs other than obtaining blocks) provided by the
- * platform. Block pools are also meant to decouple allocations from memory used by buffers. This
- * is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As
- * their name suggest, block pools maintain a pool of memory blocks. When a component asks for
- * a memory block, pools will try to return a free memory block already in the pool. If no such
- * block exists, they will allocate memory using the backing allocator and allot a block on that
- * allocation. When blocks are no longer used in the system, they are recycled back to the block
- * pool and are available as free blocks.
- *
- * Never constructed on stack.
- */
-class C2BlockPool {
-public:
- /**
- * Block pool ID type.
- */
- typedef uint64_t local_id_t;
-
- enum : local_id_t {
- BASIC_LINEAR = 0, ///< ID of basic (unoptimized) block pool for fetching 1D blocks
- BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks
- PLATFORM_START = 0x10,
- };
-
- /**
- * Returns the ID for this block pool. This ID is used to get this block pool from the platform.
- * It is only valid in the current process.
- *
- * This method MUST be "non-blocking" and return within 1ms.
- *
- * \return a local ID for this block pool.
- */
- virtual local_id_t getLocalId() const = 0;
-
- /**
- * Returns the ID of the backing allocator of this block pool.
- *
- * This method MUST be "non-blocking" and return within 1ms.
- *
- * \return the ID of the backing allocator of this block pool.
- */
- virtual C2Allocator::id_t getAllocatorId() const = 0;
-
- /**
- * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the
- * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
- *
- * \param capacity the size of requested block.
- * \param usage the memory usage info for the requested block. Returned blocks will be
- * optimized for this usage, but may be used with any usage. One exception:
- * protected blocks/buffers can only be used in a protected scenario.
- * \param block pointer to where the obtained block shall be stored on success. nullptr will
- * be stored here on failure
- *
- * \retval C2_OK the operation was successful
- * \retval C2_NO_MEMORY not enough memory to complete any required allocation
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_REFUSED no permission to complete any required allocation
- * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this pool does not support linear blocks
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
- */
- virtual c2_status_t fetchLinearBlock(
- uint32_t capacity __unused, C2MemoryUsage usage __unused,
- std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
- *block = nullptr;
- return C2_OMITTED;
- }
-
- /**
- * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the
- * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
- *
- * \param capacity the size of requested circular block. (note: the size of the obtained
- * block could be slightly larger, e.g. to accommodate any system-required
- * alignment)
- * \param usage the memory usage info for the requested block. Returned blocks will be
- * optimized for this usage, but may be used with any usage. One exception:
- * protected blocks/buffers can only be used in a protected scenario.
- * \param block pointer to where the obtained block shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the operation was successful
- * \retval C2_NO_MEMORY not enough memory to complete any required allocation
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_REFUSED no permission to complete any required allocation
- * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this pool does not support circular blocks
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
- */
- virtual c2_status_t fetchCircularBlock(
- uint32_t capacity __unused, C2MemoryUsage usage __unused,
- std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
- *block = nullptr;
- return C2_OMITTED;
- }
-
- /**
- * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
- * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
- *
- * \param width the width of requested block (the obtained block could be slightly larger, e.g.
- * to accommodate any system-required alignment)
- * \param height the height of requested block (the obtained block could be slightly larger,
- * e.g. to accommodate any system-required alignment)
- * \param format the pixel format of requested block. This could be a vendor specific format.
- * \param usage the memory usage info for the requested block. Returned blocks will be
- * optimized for this usage, but may be used with any usage. One exception:
- * protected blocks/buffers can only be used in a protected scenario.
- * \param block pointer to where the obtained block shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the operation was successful
- * \retval C2_NO_MEMORY not enough memory to complete any required allocation
- * \retval C2_TIMED_OUT the operation timed out
- * \retval C2_REFUSED no permission to complete any required allocation
- * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
- * error)
- * \retval C2_OMITTED this pool does not support 2D blocks
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
- */
- virtual c2_status_t fetchGraphicBlock(
- uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
- C2MemoryUsage usage __unused,
- std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
- *block = nullptr;
- return C2_OMITTED;
- }
-
-protected:
- C2BlockPool() = default;
-
- virtual ~C2BlockPool() = default;
-};
-
-/// @}
-
/// \cond INTERNAL
/// \todo These are no longer used
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index aa0974a..721966b 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -696,6 +696,7 @@
DEFAULT_GRAPHIC, ///< basic graphic allocator type
PLATFORM_START = 0x10,
VENDOR_START = 0x100,
+ BAD_ID = C2Allocator::BAD_ID, ///< DO NOT USE
};
/**
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index a310717..2de43c8 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -29,10 +29,10 @@
class C2BufferTest : public ::testing::Test {
public:
C2BufferTest()
- : mLinearAllocator(std::make_shared<C2AllocatorIon>()),
+ : mLinearAllocator(std::make_shared<C2AllocatorIon>('i')),
mSize(0u),
mAddr(nullptr),
- mGraphicAllocator(std::make_shared<C2AllocatorGralloc>()) {
+ mGraphicAllocator(std::make_shared<C2AllocatorGralloc>('g')) {
}
~C2BufferTest() = default;
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index a5ea511..155583d 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -540,7 +540,7 @@
return C2_OK;
}
-C2AllocatorGralloc::C2AllocatorGralloc() : mImpl(new Impl) {}
+C2AllocatorGralloc::C2AllocatorGralloc(id_t) : mImpl(new Impl) {}
C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 34c68bb..4328a8d 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -119,14 +119,14 @@
size_t offset, size_t size, C2MemoryUsage usage, int *fence,
void **addr /* nonnull */) override;
virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd) override;
- virtual bool isValid() const override;
virtual ~C2AllocationIon() override;
virtual const C2Handle *handle() const override;
+ virtual id_t getAllocatorId() const override;
virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const override;
// internal methods
- C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
- C2AllocationIon(int ionFd, size_t size, int shareFd);
+ C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags, C2Allocator::id_t id);
+ C2AllocationIon(int ionFd, size_t size, int shareFd, C2Allocator::id_t id);
c2_status_t status() const;
@@ -154,10 +154,11 @@
* invalid if err is not 0.
* \param err errno during buffer allocation or import
*/
- Impl(int ionFd, size_t capacity, int bufferFd, ion_user_handle_t buffer, int err)
+ Impl(int ionFd, size_t capacity, int bufferFd, ion_user_handle_t buffer, C2Allocator::id_t id, int err)
: mIonFd(ionFd),
mHandle(bufferFd, capacity),
mBuffer(buffer),
+ mId(id),
mInit(c2_map_errno<ENOMEM, EACCES, EINVAL>(err)),
mMapFd(-1),
mMapSize(0) {
@@ -183,10 +184,10 @@
* \return created ion allocation (implementation) which may be invalid if the
* import failed.
*/
- static Impl *Import(int ionFd, size_t capacity, int bufferFd) {
+ static Impl *Import(int ionFd, size_t capacity, int bufferFd, C2Allocator::id_t id) {
ion_user_handle_t buffer = -1;
int ret = ion_import(ionFd, bufferFd, &buffer);
- return new Impl(ionFd, capacity, bufferFd, buffer, ret);
+ return new Impl(ionFd, capacity, bufferFd, buffer, id, ret);
}
/**
@@ -201,7 +202,7 @@
* \return created ion allocation (implementation) which may be invalid if the
* allocation failed.
*/
- static Impl *Alloc(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags) {
+ static Impl *Alloc(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags, C2Allocator::id_t id) {
int bufferFd = -1;
ion_user_handle_t buffer = -1;
int ret = ion_alloc(ionFd, size, align, heapMask, flags, &buffer);
@@ -213,7 +214,7 @@
buffer = -1;
}
}
- return new Impl(ionFd, size, bufferFd, buffer, ret);
+ return new Impl(ionFd, size, bufferFd, buffer, id, ret);
}
c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
@@ -311,10 +312,19 @@
return &mHandle;
}
+ C2Allocator::id_t getAllocatorId() const {
+ return mId;
+ }
+
+ ion_user_handle_t ionHandle() const {
+ return mBuffer;
+ }
+
private:
int mIonFd;
C2HandleIon mHandle;
ion_user_handle_t mBuffer;
+ C2Allocator::id_t mId;
c2_status_t mInit;
int mMapFd; // only one for now
void *mMapAddr;
@@ -331,17 +341,21 @@
return mImpl->unmap(addr, size, fenceFd);
}
-bool C2AllocationIon::isValid() const {
- return mImpl->status() == C2_OK;
-}
-
c2_status_t C2AllocationIon::status() const {
return mImpl->status();
}
+C2Allocator::id_t C2AllocationIon::getAllocatorId() const {
+ return mImpl->getAllocatorId();
+}
+
bool C2AllocationIon::equals(const std::shared_ptr<C2LinearAllocation> &other) const {
- return other != nullptr &&
- other->handle(); // TODO
+ if (!other || other->getAllocatorId() != getAllocatorId()) {
+ return false;
+ }
+ // get user handle to compare objects
+ std::shared_ptr<C2AllocationIon> otherAsIon = std::static_pointer_cast<C2AllocationIon>(other);
+ return mImpl->ionHandle() == otherAsIon->mImpl->ionHandle();
}
const C2Handle *C2AllocationIon::handle() const {
@@ -352,21 +366,28 @@
delete mImpl;
}
-C2AllocationIon::C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags)
+C2AllocationIon::C2AllocationIon(int ionFd, size_t size, size_t align,
+ unsigned heapMask, unsigned flags, C2Allocator::id_t id)
: C2LinearAllocation(size),
- mImpl(Impl::Alloc(ionFd, size, align, heapMask, flags)) { }
+ mImpl(Impl::Alloc(ionFd, size, align, heapMask, flags, id)) { }
-C2AllocationIon::C2AllocationIon(int ionFd, size_t size, int shareFd)
+C2AllocationIon::C2AllocationIon(int ionFd, size_t size, int shareFd, C2Allocator::id_t id)
: C2LinearAllocation(size),
- mImpl(Impl::Import(ionFd, size, shareFd)) { }
+ mImpl(Impl::Import(ionFd, size, shareFd, id)) { }
/* ======================================= ION ALLOCATOR ====================================== */
-C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
+C2AllocatorIon::C2AllocatorIon(id_t id)
+ : mInit(C2_OK),
+ mIonFd(ion_open()) {
if (mIonFd < 0) {
switch (errno) {
case ENOENT: mInit = C2_OMITTED; break;
default: mInit = c2_map_errno<EACCES>(errno); break;
}
+ } else {
+ C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
+ Traits traits = { "android.allocator.ion", id, LINEAR, minUsage, maxUsage };
+ mTraits = std::make_shared<Traits>(traits);
}
}
@@ -377,11 +398,15 @@
}
C2Allocator::id_t C2AllocatorIon::getId() const {
- return 0; /// \todo implement ID
+ return mTraits->id;
}
C2String C2AllocatorIon::getName() const {
- return "android.allocator.ion";
+ return mTraits->name;
+}
+
+std::shared_ptr<const C2Allocator::Traits> C2AllocatorIon::getTraits() const {
+ return mTraits;
}
c2_status_t C2AllocatorIon::newLinearAllocation(
@@ -410,7 +435,7 @@
#endif
std::shared_ptr<C2AllocationIon> alloc
- = std::make_shared<C2AllocationIon>(dup(mIonFd), capacity, align, heapMask, flags);
+ = std::make_shared<C2AllocationIon>(dup(mIonFd), capacity, align, heapMask, flags, mTraits->id);
c2_status_t ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
@@ -432,7 +457,7 @@
// TODO: get capacity and validate it
const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
std::shared_ptr<C2AllocationIon> alloc
- = std::make_shared<C2AllocationIon>(dup(mIonFd), h->size(), h->bufferFd());
+ = std::make_shared<C2AllocationIon>(dup(mIonFd), h->size(), h->bufferFd(), mTraits->id);
c2_status_t ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 4ab3e05..ff92679 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -21,49 +21,46 @@
#include <map>
#include <C2BufferPriv.h>
+#include <C2BlockInternal.h>
namespace android {
namespace {
+// This anonymous namespace contains the helper classes that allow our implementation to create
+// block/buffer objects.
+//
// Inherit from the parent, share with the friend.
-
-class DummyCapacityAspect : public _C2LinearCapacityAspect {
- using _C2LinearCapacityAspect::_C2LinearCapacityAspect;
- friend class ::android::C2ReadView;
- friend class ::android::C2ConstLinearBlock;
-};
-
-class C2DefaultReadView : public C2ReadView {
+class ReadViewBuddy : public C2ReadView {
using C2ReadView::C2ReadView;
friend class ::android::C2ConstLinearBlock;
};
-class C2DefaultWriteView : public C2WriteView {
+class WriteViewBuddy : public C2WriteView {
using C2WriteView::C2WriteView;
friend class ::android::C2LinearBlock;
};
-class C2AcquirableReadView : public C2Acquirable<C2ReadView> {
- using C2Acquirable::C2Acquirable;
- friend class ::android::C2ConstLinearBlock;
-};
-
-class C2AcquirableWriteView : public C2Acquirable<C2WriteView> {
- using C2Acquirable::C2Acquirable;
- friend class ::android::C2LinearBlock;
-};
-
-class C2DefaultConstLinearBlock : public C2ConstLinearBlock {
+class ConstLinearBlockBuddy : public C2ConstLinearBlock {
using C2ConstLinearBlock::C2ConstLinearBlock;
friend class ::android::C2LinearBlock;
};
-class C2DefaultLinearBlock : public C2LinearBlock {
+class LinearBlockBuddy : public C2LinearBlock {
using C2LinearBlock::C2LinearBlock;
friend class ::android::C2BasicLinearBlockPool;
};
+class AcquirableReadViewBuddy : public C2Acquirable<C2ReadView> {
+ using C2Acquirable::C2Acquirable;
+ friend class ::android::C2ConstLinearBlock;
+};
+
+class AcquirableWriteViewBuddy : public C2Acquirable<C2WriteView> {
+ using C2Acquirable::C2Acquirable;
+ friend class ::android::C2LinearBlock;
+};
+
class C2DefaultGraphicView : public C2GraphicView {
using C2GraphicView::C2GraphicView;
friend class ::android::C2ConstGraphicBlock;
@@ -99,255 +96,230 @@
/* ========================================== 1D BLOCK ========================================= */
-class C2Block1D::Impl {
+struct C2_HIDE _C2BlockPoolData;
+
+/**
+ * This class is the base class for all 1D block and view implementations.
+ *
+ * This is basically just a placeholder for the underlying 1D allocation and the range of the
+ * alloted portion to this block. There is also a placeholder for a blockpool data.
+ */
+class C2_HIDE _C2Block1DImpl : public _C2LinearRangeAspect {
public:
- const C2Handle *handle() const {
- return mAllocation->handle();
+ _C2Block1DImpl(const std::shared_ptr<C2LinearAllocation> &alloc,
+ const std::shared_ptr<_C2BlockPoolData> &poolData = nullptr,
+ size_t offset = 0, size_t size = ~(size_t)0)
+ : _C2LinearRangeAspect(alloc.get(), offset, size),
+ mAllocation(alloc),
+ mPoolData(poolData) { }
+
+ _C2Block1DImpl(const _C2Block1DImpl &other, size_t offset = 0, size_t size = ~(size_t)0)
+ : _C2LinearRangeAspect(&other, offset, size),
+ mAllocation(other.mAllocation),
+ mPoolData(other.mPoolData) { }
+
+ /** returns const pool data */
+ std::shared_ptr<const _C2BlockPoolData> poolData() const {
+ return mPoolData;
}
- Impl(std::shared_ptr<C2LinearAllocation> alloc)
- : mAllocation(alloc) {}
+ /** returns native handle */
+ const C2Handle *handle() const {
+ return mAllocation ? mAllocation->handle() : nullptr;
+ }
+
+ /** returns the allocator's ID */
+ C2Allocator::id_t getAllocatorId() const {
+ // BAD_ID can only happen if this Impl class is initialized for a view - never for a block.
+ return mAllocation ? mAllocation->getAllocatorId() : C2Allocator::BAD_ID;
+ }
+
+ std::shared_ptr<C2LinearAllocation> getAllocation() const {
+ return mAllocation;
+ }
private:
std::shared_ptr<C2LinearAllocation> mAllocation;
+ std::shared_ptr<_C2BlockPoolData> mPoolData;
};
-const C2Handle *C2Block1D::handle() const {
- return mImpl->handle();
-};
-
-C2Block1D::C2Block1D(std::shared_ptr<C2LinearAllocation> alloc)
- : _C2LinearRangeAspect(alloc.get()), mImpl(new Impl(alloc)) {
-}
-
-C2Block1D::C2Block1D(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size)
- : _C2LinearRangeAspect(alloc.get(), offset, size), mImpl(new Impl(alloc)) {
-}
-
-class C2ReadView::Impl {
+/**
+ * This class contains the mapped data pointer, and the potential error.
+ *
+ * range is the mapped range of the underlying allocation (which is part of the allotted
+ * range).
+ */
+class C2_HIDE _C2MappedBlock1DImpl : public _C2Block1DImpl {
public:
- explicit Impl(const uint8_t *data)
- : mData(data), mError(C2_OK) {}
+ _C2MappedBlock1DImpl(const _C2Block1DImpl &block, uint8_t *data,
+ size_t offset = 0, size_t size = ~(size_t)0)
+ : _C2Block1DImpl(block, offset, size), mData(data), mError(C2_OK) { }
- explicit Impl(c2_status_t error)
- : mData(nullptr), mError(error) {}
+ _C2MappedBlock1DImpl(c2_status_t error)
+ : _C2Block1DImpl(nullptr), mData(nullptr), mError(error) {
+ // CHECK(error != C2_OK);
+ }
const uint8_t *data() const {
return mData;
}
+ uint8_t *data() {
+ return mData;
+ }
+
c2_status_t error() const {
return mError;
}
private:
- const uint8_t *mData;
+ uint8_t *mData;
c2_status_t mError;
};
-C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
- : _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
+/**
+ * Block implementation.
+ */
+class C2Block1D::Impl : public _C2Block1DImpl {
+ using _C2Block1DImpl::_C2Block1DImpl;
+};
-C2ReadView::C2ReadView(c2_status_t error)
- : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
+const C2Handle *C2Block1D::handle() const {
+ return mImpl->handle();
+};
-const uint8_t *C2ReadView::data() const {
- return mImpl->data();
+C2Allocator::id_t C2Block1D::getAllocatorId() const {
+ return mImpl->getAllocatorId();
+};
+
+C2Block1D::C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range)
+ // always clamp subrange to parent (impl) range for safety
+ : _C2LinearRangeAspect(impl.get(), range.offset(), range.size()), mImpl(impl) {
}
-C2ReadView C2ReadView::subView(size_t offset, size_t size) const {
- if (offset > capacity()) {
- offset = capacity();
- }
- if (size > capacity() - offset) {
- size = capacity() - offset;
- }
- // TRICKY: newCapacity will just be used to grab the size.
- DummyCapacityAspect newCapacity((uint32_t)size);
- return C2ReadView(&newCapacity, data() + offset);
+/**
+ * Read view implementation.
+ *
+ * range of Impl is the mapped range of the underlying allocation (which is part of the allotted
+ * range). range of View is 0 to capacity() (not represented as an actual range). This maps to a
+ * subrange of Impl range starting at mImpl->offset() + _mOffset.
+ */
+class C2ReadView::Impl : public _C2MappedBlock1DImpl {
+ using _C2MappedBlock1DImpl::_C2MappedBlock1DImpl;
+};
+
+C2ReadView::C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size)
+ : _C2LinearCapacityAspect(C2LinearCapacity(impl->size()).range(offset, size).size()),
+ mImpl(impl),
+ mOffset(C2LinearCapacity(impl->size()).range(offset, size).offset()) { }
+
+C2ReadView::C2ReadView(c2_status_t error)
+ : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)), mOffset(0u) {
+ // CHECK(error != C2_OK);
+}
+
+const uint8_t *C2ReadView::data() const {
+ return mImpl->error() ? nullptr : mImpl->data() + mOffset;
}
c2_status_t C2ReadView::error() const {
return mImpl->error();
}
-class C2WriteView::Impl {
-public:
- explicit Impl(uint8_t *base)
- : mBase(base), mError(C2_OK) {}
+C2ReadView C2ReadView::subView(size_t offset, size_t size) const {
+ C2LinearRange subRange(*this, offset, size);
+ return C2ReadView(mImpl, mOffset + subRange.offset(), subRange.size());
+}
- explicit Impl(c2_status_t error)
- : mBase(nullptr), mError(error) {}
-
- uint8_t *base() const {
- return mBase;
- }
-
- c2_status_t error() const {
- return mError;
- }
-
-private:
- uint8_t *mBase;
- c2_status_t mError;
+/**
+ * Write view implementation.
+ */
+class C2WriteView::Impl : public _C2MappedBlock1DImpl {
+ using _C2MappedBlock1DImpl::_C2MappedBlock1DImpl;
};
-C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
- : _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
+C2WriteView::C2WriteView(std::shared_ptr<Impl> impl)
+// UGLY: _C2LinearRangeAspect requires a bona-fide object for capacity to prevent spoofing, so
+// this is what we have to do.
+ : _C2EditableLinearRange(std::make_unique<C2LinearCapacity>(impl->size()).get()), mImpl(impl) { }
C2WriteView::C2WriteView(c2_status_t error)
: _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
-uint8_t *C2WriteView::base() { return mImpl->base(); }
+uint8_t *C2WriteView::base() { return mImpl->data(); }
-uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
+uint8_t *C2WriteView::data() { return mImpl->data() + offset(); }
c2_status_t C2WriteView::error() const { return mImpl->error(); }
-class C2ConstLinearBlock::Impl {
-public:
- explicit Impl(std::shared_ptr<C2LinearAllocation> alloc)
- : mAllocation(alloc), mBase(nullptr), mSize(0u), mError(C2_CORRUPTED) {}
-
- ~Impl() {
- if (mBase != nullptr) {
- // TODO: fence
- c2_status_t err = mAllocation->unmap(mBase, mSize, nullptr);
- if (err != C2_OK) {
- // TODO: Log?
- }
- }
- }
-
- C2ConstLinearBlock subBlock(size_t offset, size_t size) const {
- return C2ConstLinearBlock(mAllocation, offset, size);
- }
-
- void map(size_t offset, size_t size) {
- if (mBase == nullptr) {
- void *base = nullptr;
- mError = mAllocation->map(
- offset, size, { C2MemoryUsage::CPU_READ, 0 }, nullptr, &base);
- // TODO: fence
- if (mError == C2_OK) {
- mBase = (uint8_t *)base;
- mSize = size;
- }
- }
- }
-
- const uint8_t *base() const { return mBase; }
-
- c2_status_t error() const { return mError; }
-
-private:
- std::shared_ptr<C2LinearAllocation> mAllocation;
- uint8_t *mBase;
- size_t mSize;
- c2_status_t mError;
-};
-
-C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
- : C2Block1D(alloc), mImpl(std::make_shared<Impl>(alloc)) {}
-
-C2ConstLinearBlock::C2ConstLinearBlock(
- std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size)
- : C2Block1D(alloc, offset, size), mImpl(std::make_shared<Impl>(alloc)) {}
+/**
+ * Const linear block implementation.
+ */
+C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence fence)
+ : C2Block1D(impl, range), mFence(fence) { }
C2Acquirable<C2ReadView> C2ConstLinearBlock::map() const {
- mImpl->map(offset(), size());
- if (mImpl->base() == nullptr) {
- C2DefaultReadView view(mImpl->error());
- return C2AcquirableReadView(mImpl->error(), mFence, view);
+ void *base = nullptr;
+ uint32_t len = size();
+ c2_status_t error = mImpl->getAllocation()->map(
+ offset(), len, { C2MemoryUsage::CPU_READ, 0 }, nullptr, &base);
+ // TODO: wait on fence
+ if (error == C2_OK) {
+ std::shared_ptr<ReadViewBuddy::Impl> rvi = std::shared_ptr<ReadViewBuddy::Impl>(
+ new ReadViewBuddy::Impl(*mImpl, (uint8_t *)base, offset(), len),
+ [base, len](ReadViewBuddy::Impl *i) {
+ (void)i->getAllocation()->unmap(base, len, nullptr);
+ });
+ return AcquirableReadViewBuddy(error, C2Fence(), ReadViewBuddy(rvi, 0, len));
+ } else {
+ return AcquirableReadViewBuddy(error, C2Fence(), ReadViewBuddy(error));
}
- DummyCapacityAspect newCapacity(size());
- C2DefaultReadView view(&newCapacity, mImpl->base());
- return C2AcquirableReadView(mImpl->error(), mFence, view);
}
-C2ConstLinearBlock C2ConstLinearBlock::subBlock(size_t offset, size_t size) const {
- return mImpl->subBlock(offset, size);
+C2ConstLinearBlock C2ConstLinearBlock::subBlock(size_t offset_, size_t size_) const {
+ C2LinearRange subRange(*mImpl, offset_, size_);
+ return C2ConstLinearBlock(mImpl, subRange, mFence);
}
-class C2LinearBlock::Impl {
-public:
- Impl(std::shared_ptr<C2LinearAllocation> alloc)
- : mAllocation(alloc), mBase(nullptr), mSize(0u), mError(C2_CORRUPTED) {}
-
- ~Impl() {
- if (mBase != nullptr) {
- // TODO: fence
- c2_status_t err = mAllocation->unmap(mBase, mSize, nullptr);
- if (err != C2_OK) {
- // TODO: Log?
- }
- }
- }
-
- void map(size_t capacity) {
- if (mBase == nullptr) {
- void *base = nullptr;
- // TODO: fence
- mError = mAllocation->map(
- 0u,
- capacity,
- { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
- nullptr,
- &base);
- if (mError == C2_OK) {
- mBase = (uint8_t *)base;
- mSize = capacity;
- }
- }
- }
-
- C2ConstLinearBlock share(size_t offset, size_t size, C2Fence &fence) {
- // TODO
- (void) fence;
- return C2DefaultConstLinearBlock(mAllocation, offset, size);
- }
-
- uint8_t *base() const { return mBase; }
-
- c2_status_t error() const { return mError; }
-
- C2Fence fence() const { return mFence; }
-
-private:
- std::shared_ptr<C2LinearAllocation> mAllocation;
- uint8_t *mBase;
- size_t mSize;
- c2_status_t mError;
- C2Fence mFence;
-};
-
-C2LinearBlock::C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
- : C2Block1D(alloc),
- mImpl(new Impl(alloc)) {}
-
-C2LinearBlock::C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size)
- : C2Block1D(alloc, offset, size),
- mImpl(new Impl(alloc)) {}
+/**
+ * Linear block implementation.
+ */
+C2LinearBlock::C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range)
+ : C2Block1D(impl, range) { }
C2Acquirable<C2WriteView> C2LinearBlock::map() {
- mImpl->map(capacity());
- if (mImpl->base() == nullptr) {
- C2DefaultWriteView view(mImpl->error());
- return C2AcquirableWriteView(mImpl->error(), mImpl->fence(), view);
+ void *base = nullptr;
+ uint32_t len = size();
+ c2_status_t error = mImpl->getAllocation()->map(
+ offset(), len, { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, nullptr, &base);
+ // TODO: wait on fence
+ if (error == C2_OK) {
+ std::shared_ptr<WriteViewBuddy::Impl> rvi = std::shared_ptr<WriteViewBuddy::Impl>(
+ new WriteViewBuddy::Impl(*mImpl, (uint8_t *)base, 0, len),
+ [base, len](WriteViewBuddy::Impl *i) {
+ (void)i->getAllocation()->unmap(base, len, nullptr);
+ });
+ return AcquirableWriteViewBuddy(error, C2Fence(), WriteViewBuddy(rvi));
+ } else {
+ return AcquirableWriteViewBuddy(error, C2Fence(), WriteViewBuddy(error));
}
- C2DefaultWriteView view(this, mImpl->base());
- view.setOffset_be(offset());
- view.setSize_be(size());
- return C2AcquirableWriteView(mImpl->error(), mImpl->fence(), view);
}
-C2ConstLinearBlock C2LinearBlock::share(size_t offset, size_t size, C2Fence fence) {
- return mImpl->share(offset, size, fence);
+C2ConstLinearBlock C2LinearBlock::share(size_t offset_, size_t size_, C2Fence fence) {
+ return ConstLinearBlockBuddy(mImpl, C2LinearRange(*this, offset_, size_), fence);
+}
+
+std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
+ const std::shared_ptr<C2LinearAllocation> &alloc,
+ const std::shared_ptr<_C2BlockPoolData> &data, size_t offset, size_t size) {
+ std::shared_ptr<C2Block1D::Impl> impl =
+ std::make_shared<C2Block1D::Impl>(alloc, data, offset, size);
+ return std::shared_ptr<C2LinearBlock>(new C2LinearBlock(impl, *impl));
}
C2BasicLinearBlockPool::C2BasicLinearBlockPool(
const std::shared_ptr<C2Allocator> &allocator)
- : mAllocator(allocator) {}
+ : mAllocator(allocator) { }
c2_status_t C2BasicLinearBlockPool::fetchLinearBlock(
uint32_t capacity,
@@ -361,7 +333,7 @@
return err;
}
- block->reset(new C2DefaultLinearBlock(alloc));
+ *block = _C2BlockFactory::CreateLinearBlock(alloc);
return C2_OK;
}
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index a49fd24..05b46c3 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -40,14 +40,9 @@
* \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags
* \todo Make this allocator store extendable
*/
-class C2PlatformAllocatorStore : public C2AllocatorStore {
+class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
public:
- enum : id_t {
- ION = PLATFORM_START,
- GRALLOC,
- };
-
- C2PlatformAllocatorStore(
+ C2PlatformAllocatorStoreImpl(
/* ionmapper */
);
@@ -71,10 +66,10 @@
std::shared_ptr<C2Allocator> fetchGrallocAllocator();
};
-C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
+C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
}
-c2_status_t C2PlatformAllocatorStore::fetchAllocator(
+c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
id_t id, std::shared_ptr<C2Allocator> *const allocator) {
allocator->reset();
switch (id) {
@@ -98,32 +93,32 @@
return C2_OK;
}
-std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::fetchIonAllocator() {
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
static std::mutex mutex;
static std::weak_ptr<C2Allocator> ionAllocator;
std::lock_guard<std::mutex> lock(mutex);
std::shared_ptr<C2Allocator> allocator = ionAllocator.lock();
if (allocator == nullptr) {
- allocator = std::make_shared<C2AllocatorIon>();
+ allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
ionAllocator = allocator;
}
return allocator;
}
-std::shared_ptr<C2Allocator> C2PlatformAllocatorStore::fetchGrallocAllocator() {
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
static std::mutex mutex;
static std::weak_ptr<C2Allocator> grallocAllocator;
std::lock_guard<std::mutex> lock(mutex);
std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
if (allocator == nullptr) {
- allocator = std::make_shared<C2AllocatorGralloc>();
+ allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
grallocAllocator = allocator;
}
return allocator;
}
std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
- return std::make_shared<C2PlatformAllocatorStore>();
+ return std::make_shared<C2PlatformAllocatorStoreImpl>();
}
c2_status_t GetCodec2BlockPool(
@@ -408,6 +403,8 @@
mComponents.emplace("c2.google.aac.decoder", "libstagefright_soft_c2aacdec.so");
mComponents.emplace("c2.google.aac.encoder", "libstagefright_soft_c2aacenc.so");
mComponents.emplace("c2.google.mp3.decoder", "libstagefright_soft_c2mp3dec.so");
+ mComponents.emplace("c2.google.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so");
+ mComponents.emplace("c2.google.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so");
}
c2_status_t C2PlatformComponentStore::copyBuffer(
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 56fa317..0e1a3ac 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -61,7 +61,7 @@
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
- C2AllocatorGralloc();
+ C2AllocatorGralloc(id_t id = 0);
c2_status_t status() const;
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index bb815f9..716eae0 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -33,9 +33,7 @@
virtual C2String getName() const override;
- virtual std::shared_ptr<const Traits> getTraits() const override {
- return nullptr; // \todo
- }
+ virtual std::shared_ptr<const Traits> getTraits() const override;
virtual c2_status_t newLinearAllocation(
uint32_t capacity, C2MemoryUsage usage,
@@ -45,13 +43,14 @@
const C2Handle *handle,
std::shared_ptr<C2LinearAllocation> *allocation) override;
- C2AllocatorIon();
+ C2AllocatorIon(id_t id);
virtual c2_status_t status() const { return mInit; }
virtual ~C2AllocatorIon() override;
private:
+ std::shared_ptr<const Traits> mTraits;
c2_status_t mInit;
int mIonFd;
usage_mapper_fn mUsageMapper;
diff --git a/media/libstagefright/codec2/vndk/include/C2ComponentFactory.h b/media/libstagefright/codec2/vndk/include/C2ComponentFactory.h
new file mode 100644
index 0000000..cfea104
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/include/C2ComponentFactory.h
@@ -0,0 +1,89 @@
+/*
+ * 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 STAGEFRIGHT_CODEC2_COMPONENT_FACTORY_H_
+#define STAGEFRIGHT_CODEC2_COMPONENT_FACTORY_H_
+
+#include <C2Component.h>
+
+#include <functional>
+#include <memory>
+
+namespace android {
+
+/**
+ * Component factory object that enables to create a component and/or interface from a dynamically
+ * linked library. This is needed because the component/interfaces are managed objects, but we
+ * cannot safely create a managed object and pass it in C.
+ *
+ * Components/interfaces typically inherit from std::enable_shared_from_this, but C requires
+ * passing simple pointer, and shared_ptr constructor needs to know the class to be constructed
+ * derives from enable_shared_from_this.
+ *
+ */
+class C2ComponentFactory {
+public:
+ typedef std::function<void(::android::C2Component*)> ComponentDeleter;
+ typedef std::function<void(::android::C2ComponentInterface*)> InterfaceDeleter;
+
+ /**
+ * Creates a component.
+ *
+ * This method SHALL return within 100ms.
+ *
+ * \param id component ID for the created component
+ * \param component shared pointer where the created component is stored. Cleared on
+ * failure and updated on success.
+ *
+ * \retval C2_OK the component was created successfully
+ * \retval C2_TIMED_OUT could not create the component within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the component (unexpected)
+ *
+ * \retval C2_NO_MEMORY not enough memory to create the component
+ */
+ virtual c2_status_t createComponent(
+ c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ ComponentDeleter deleter = std::default_delete<C2Component>()) = 0;
+
+ /**
+ * Creates a component interface.
+ *
+ * This method SHALL return within 100ms.
+ *
+ * \param id component interface ID for the created interface
+ * \param interface shared pointer where the created interface is stored. Cleared on
+ * failure and updated on success.
+ *
+ * \retval C2_OK the component interface was created successfully
+ * \retval C2_TIMED_OUT could not create the component interface within the time limit
+ * (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the component interface
+ * (unexpected)
+ *
+ * \retval C2_NO_MEMORY not enough memory to create the component interface
+ */
+ virtual c2_status_t createInterface(
+ c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+ InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) = 0;
+
+ virtual ~C2ComponentFactory() = default;
+
+ typedef ::android::C2ComponentFactory* (*CreateCodec2FactoryFunc)(void);
+ typedef void (*DestroyCodec2FactoryFunc)(::android::C2ComponentFactory*);
+};
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_COMPONENT_FACTORY_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
index 2281dab..76b02ed 100644
--- a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
@@ -18,8 +18,8 @@
#define STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
#include <C2Component.h>
+#include <C2ComponentFactory.h>
-#include <functional>
#include <memory>
namespace android {
@@ -31,6 +31,34 @@
std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore();
/**
+ * Platform allocator store IDs
+ */
+class C2PlatformAllocatorStore : public C2AllocatorStore {
+public:
+ enum : id_t {
+ /**
+ * ID of the ion backed platform allocator.
+ *
+ * C2Handle consists of:
+ * fd shared ion buffer handle
+ * int size (lo 32 bits)
+ * int size (hi 32 bits)
+ * int magic '\xc2io\x00'
+ */
+ ION = PLATFORM_START,
+
+ /**
+ * ID of the gralloc backed platform allocator.
+ *
+ * C2Handle layout is not public. Use C2AllocatorGralloc::UnwrapNativeCodec2GrallocHandle
+ * to get the underlying gralloc handle from a C2Handle, and WrapNativeCodec2GrallocHandle
+ * to create a C2Handle from a gralloc handle - for C2Allocator::priorAllocation.
+ */
+ GRALLOC,
+ };
+};
+
+/**
* Retrieves a block pool for a component.
*
* \param id the local ID of the block pool
@@ -54,73 +82,10 @@
std::shared_ptr<C2BlockPool> *pool);
/**
- * Component factory object that enables to create a component and/or interface from a dynamically
- * linked library. This is needed because the component/interfaces are managed objects, but we
- * cannot safely create a managed object and pass it in C.
- *
- * Components/interfaces typically inherit from std::enable_shared_from_this, but C requires
- * passing simple pointer, and shared_ptr constructor needs to know the class to be constructed
- * derives from enable_shared_from_this.
- *
- */
-class C2ComponentFactory {
-public:
- typedef std::function<void(::android::C2Component*)> ComponentDeleter;
- typedef std::function<void(::android::C2ComponentInterface*)> InterfaceDeleter;
-
- /**
- * Creates a component.
- *
- * This method SHALL return within 100ms.
- *
- * \param id component ID for the created component
- * \param component shared pointer where the created component is stored. Cleared on
- * failure and updated on success.
- *
- * \retval C2_OK the component was created successfully
- * \retval C2_TIMED_OUT could not create the component within the time limit (unexpected)
- * \retval C2_CORRUPTED some unknown error prevented the creation of the component (unexpected)
- *
- * \retval C2_NO_MEMORY not enough memory to create the component
- */
- virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- ComponentDeleter deleter = std::default_delete<C2Component>()) = 0;
-
- /**
- * Creates a component interface.
- *
- * This method SHALL return within 100ms.
- *
- * \param id component interface ID for the created interface
- * \param interface shared pointer where the created interface is stored. Cleared on
- * failure and updated on success.
- *
- * \retval C2_OK the component interface was created successfully
- * \retval C2_TIMED_OUT could not create the component interface within the time limit
- * (unexpected)
- * \retval C2_CORRUPTED some unknown error prevented the creation of the component interface
- * (unexpected)
- *
- * \retval C2_NO_MEMORY not enough memory to create the component interface
- */
- virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) = 0;
-
- virtual ~C2ComponentFactory() = default;
-
- typedef ::android::C2ComponentFactory* (*CreateCodec2FactoryFunc)(void);
- typedef void (*DestroyCodec2FactoryFunc)(::android::C2ComponentFactory*);
-};
-
-/**
* Returns the platform component store.
* \retval nullptr if the platform component store could not be obtained
*/
std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore();
-
-
} // namespace android
#endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/libstagefright/codec2/vndk/internal/C2BlockInternal.h b/media/libstagefright/codec2/vndk/internal/C2BlockInternal.h
new file mode 100644
index 0000000..c84d1fb
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/internal/C2BlockInternal.h
@@ -0,0 +1,41 @@
+/*
+ * 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 ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
+#define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
+
+#include <C2Buffer.h>
+
+namespace android {
+
+struct _C2BlockPoolData;
+
+/**
+ * Interface for creating blocks by block pool/buffer passing implementations.
+ */
+struct C2_HIDE _C2BlockFactory {
+ static
+ std::shared_ptr<C2LinearBlock> C2_HIDE CreateLinearBlock(
+ const std::shared_ptr<C2LinearAllocation> &alloc,
+ const std::shared_ptr<_C2BlockPoolData> &data = nullptr,
+ size_t offset = 0,
+ size_t size = ~(size_t)0);
+};
+
+}
+
+#endif // ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
+
diff --git a/media/libstagefright/codecs/g711/dec/Android.bp b/media/libstagefright/codecs/g711/dec/Android.bp
index 3d97d8c..58a0a4d 100644
--- a/media/libstagefright/codecs/g711/dec/Android.bp
+++ b/media/libstagefright/codecs/g711/dec/Android.bp
@@ -1,4 +1,79 @@
cc_library_shared {
+ name: "libstagefright_soft_c2g711alawdec",
+// vendor_available: true,
+// vndk: {
+// enabled: true,
+// },
+
+ srcs: [
+ "C2SoftG711.cpp",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DALAW",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ ],
+ cfi: true,
+ diag: {
+ cfi: true,
+ },
+ },
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libstagefright_codec2",
+ "libstagefright_codec2_vndk",
+ "libstagefright_foundation",
+ "libstagefright_simple_c2component",
+ ],
+}
+
+cc_library_shared {
+ name: "libstagefright_soft_c2g711mlawdec",
+// vendor_available: true,
+// vndk: {
+// enabled: true,
+// },
+
+ srcs: [
+ "C2SoftG711.cpp",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ ],
+ cfi: true,
+ diag: {
+ cfi: true,
+ },
+ },
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libstagefright_codec2",
+ "libstagefright_codec2_vndk",
+ "libstagefright_foundation",
+ "libstagefright_simple_c2component",
+ ],
+}
+
+cc_library_shared {
name: "libstagefright_soft_g711dec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
new file mode 100644
index 0000000..a26dbb9
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
@@ -0,0 +1,239 @@
+/*
+ * 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 "C2SoftG711"
+#include <utils/Log.h>
+
+#include "C2SoftG711.h"
+
+#include <C2PlatformSupport.h>
+#include <SimpleC2Interface.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+#ifdef ALAW
+#define COMPONENT_NAME "g711a"
+#else
+#define COMPONENT_NAME "g711m"
+#endif
+
+namespace android {
+
+C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
+ : SimpleC2Component(
+ SimpleC2Interface::Builder(name, id)
+ .inputFormat(C2FormatCompressed)
+ .outputFormat(C2FormatAudio)
+ .build()) {
+}
+
+C2SoftG711::~C2SoftG711() {
+ onRelease();
+}
+
+c2_status_t C2SoftG711::onInit() {
+ mSignalledOutputEos = false;
+ return C2_OK;
+}
+
+c2_status_t C2SoftG711::onStop() {
+ mSignalledOutputEos = false;
+ return C2_OK;
+}
+
+void C2SoftG711::onReset() {
+ (void)onStop();
+}
+
+void C2SoftG711::onRelease() {
+}
+
+c2_status_t C2SoftG711::onFlush_sm() {
+ return onStop();
+}
+
+void C2SoftG711::process(
+ const std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ work->result = C2_OK;
+ work->workletsProcessed = 0u;
+ if (mSignalledOutputEos) {
+ work->result = C2_BAD_VALUE;
+ return;
+ }
+
+ const C2ConstLinearBlock &inBuffer =
+ work->input.buffers[0]->data().linearBlocks().front();
+ C2ReadView rView = inBuffer.map().get();
+ size_t inOffset = inBuffer.offset();
+ size_t inSize = inBuffer.size();
+ int outSize = inSize * sizeof(int16_t);
+ if (inSize && rView.error()) {
+ ALOGE("read view map failed %d", rView.error());
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
+
+ ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
+ (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
+
+ if (inSize == 0) {
+ work->worklets.front()->output.flags = work->input.flags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->workletsProcessed = 1u;
+ if (eos) {
+ mSignalledOutputEos = true;
+ ALOGV("signalled EOS");
+ }
+ return;
+ }
+
+ uint8_t *inputptr = const_cast<uint8_t *>(rView.data() + inOffset);
+
+ std::shared_ptr<C2LinearBlock> block;
+ C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+ c2_status_t err = pool->fetchLinearBlock(outSize, usage, &block);
+ if (err != C2_OK) {
+ ALOGE("fetchLinearBlock for Output failed with status %d", err);
+ work->result = C2_NO_MEMORY;
+ return;
+ }
+ C2WriteView wView = block->map().get();
+ if (wView.error()) {
+ ALOGE("write view map failed %d", wView.error());
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ int16_t *outputptr = reinterpret_cast<int16_t *>(wView.data());
+
+#ifdef ALAW
+ DecodeALaw(outputptr, inputptr, inSize);
+#else
+ DecodeMLaw(outputptr, inputptr, inSize);
+#endif
+
+ work->worklets.front()->output.flags = work->input.flags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->workletsProcessed = 1u;
+
+ if (eos) {
+ mSignalledOutputEos = true;
+ ALOGV("signalled EOS");
+ }
+}
+
+c2_status_t C2SoftG711::drain(
+ uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ (void) pool;
+ if (drainMode == NO_DRAIN) {
+ ALOGW("drain with NO_DRAIN: no-op");
+ return C2_OK;
+ }
+ if (drainMode == DRAIN_CHAIN) {
+ ALOGW("DRAIN_CHAIN not supported");
+ return C2_OMITTED;
+ }
+
+ return C2_OK;
+}
+
+#ifdef ALAW
+void C2SoftG711::DecodeALaw(
+ int16_t *out, const uint8_t *in, size_t inSize) {
+ while (inSize > 0) {
+ inSize--;
+ int32_t x = *in++;
+
+ int32_t ix = x ^ 0x55;
+ ix &= 0x7f;
+
+ int32_t iexp = ix >> 4;
+ int32_t mant = ix & 0x0f;
+
+ if (iexp > 0) {
+ mant += 16;
+ }
+
+ mant = (mant << 4) + 8;
+
+ if (iexp > 1) {
+ mant = mant << (iexp - 1);
+ }
+
+ *out++ = (x > 127) ? mant : -mant;
+ }
+}
+#else
+void C2SoftG711::DecodeMLaw(
+ int16_t *out, const uint8_t *in, size_t inSize) {
+ while (inSize > 0) {
+ inSize--;
+ int32_t x = *in++;
+
+ int32_t mantissa = ~x;
+ int32_t exponent = (mantissa >> 4) & 7;
+ int32_t segment = exponent + 1;
+ mantissa &= 0x0f;
+
+ int32_t step = 4 << segment;
+
+ int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
+
+ *out++ = (x < 0x80) ? -abs : abs;
+ }
+}
+#endif
+
+class C2SoftG711DecFactory : public C2ComponentFactory {
+public:
+ virtual c2_status_t createComponent(
+ c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ std::function<void(::android::C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftG711(COMPONENT_NAME, id), deleter);
+ return C2_OK;
+ }
+
+ virtual c2_status_t createInterface(
+ c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(::android::C2ComponentInterface*)> deleter) override {
+ *interface =
+ SimpleC2Interface::Builder(COMPONENT_NAME, id, deleter)
+ .inputFormat(C2FormatCompressed)
+ .outputFormat(C2FormatAudio)
+ .build();
+ return C2_OK;
+ }
+
+ virtual ~C2SoftG711DecFactory() override = default;
+};
+
+} // namespace android
+
+extern "C" ::android::C2ComponentFactory* CreateCodec2Factory() {
+ ALOGV("in %s", __func__);
+ return new ::android::C2SoftG711DecFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory* factory) {
+ ALOGV("in %s", __func__);
+ delete factory;
+}
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.h b/media/libstagefright/codecs/g711/dec/C2SoftG711.h
new file mode 100644
index 0000000..eed38c9
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/C2SoftG711.h
@@ -0,0 +1,56 @@
+/*
+ * 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 C2_SOFT_G711_H_
+#define C2_SOFT_G711_H_
+
+#include <SimpleC2Component.h>
+
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+struct C2SoftG711 : public SimpleC2Component {
+ C2SoftG711(const char *name, c2_node_id_t id);
+ virtual ~C2SoftG711();
+
+ // From SimpleC2Component
+ c2_status_t onInit() override;
+ c2_status_t onStop() override;
+ void onReset() override;
+ void onRelease() override;
+ c2_status_t onFlush_sm() override;
+ void process(
+ const std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) override;
+ c2_status_t drain(
+ uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool> &pool) override;
+private:
+ bool mSignalledOutputEos;
+
+#ifdef ALAW
+ void DecodeALaw(int16_t *out, const uint8_t *in, size_t inSize);
+#else
+ void DecodeMLaw(int16_t *out, const uint8_t *in, size_t inSize);
+#endif
+
+ DISALLOW_EVIL_CONSTRUCTORS(C2SoftG711);
+};
+
+} // namespace android
+
+#endif // C2_SOFT_G711_H_
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 61403be..f4bba59 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -30,7 +30,7 @@
static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
-struct MemorySource : public DataSource {
+struct MemorySource : public DataSourceBase {
MemorySource(const uint8_t *data, size_t size)
: mData(data),
mSize(size) {
@@ -56,7 +56,7 @@
DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
};
-ID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset)
+ID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
: mIsValid(false),
mData(NULL),
mSize(0),
@@ -77,7 +77,7 @@
mFirstFrameOffset(0),
mVersion(ID3_UNKNOWN),
mRawSize(0) {
- sp<MemorySource> source = new (std::nothrow) MemorySource(data, size);
+ MemorySource *source = new (std::nothrow) MemorySource(data, size);
if (source == NULL)
return;
@@ -87,6 +87,7 @@
if (!mIsValid && !ignoreV1) {
mIsValid = parseV1(source);
}
+ delete source;
}
ID3::~ID3() {
@@ -118,7 +119,7 @@
return true;
}
-bool ID3::parseV2(const sp<DataSource> &source, off64_t offset) {
+bool ID3::parseV2(DataSourceBase *source, off64_t offset) {
struct id3_header {
char id[3];
uint8_t version_major;
@@ -960,7 +961,7 @@
return NULL;
}
-bool ID3::parseV1(const sp<DataSource> &source) {
+bool ID3::parseV1(DataSourceBase *source) {
const size_t V1_TAG_SIZE = 128;
off64_t size;
diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
index 442a3ff..86e6adf 100644
--- a/media/libstagefright/id3/testid3.cpp
+++ b/media/libstagefright/id3/testid3.cpp
@@ -72,7 +72,7 @@
sp<FileSource> file = new FileSource(path);
CHECK_EQ(file->initCheck(), (status_t)OK);
- ID3 tag(file);
+ ID3 tag(file.get());
if (!tag.isValid()) {
printf("FAIL %s\n", path);
} else {
diff --git a/media/libstagefright/include/Codec2Buffer.h b/media/libstagefright/include/Codec2Buffer.h
index 0272cea..6d85e83 100644
--- a/media/libstagefright/include/Codec2Buffer.h
+++ b/media/libstagefright/include/Codec2Buffer.h
@@ -24,30 +24,48 @@
namespace android {
-class C2Buffer;
-
/**
* MediaCodecBuffer implementation wraps around C2LinearBlock.
*/
-class Codec2Buffer : public MediaCodecBuffer {
+class LinearBlockBuffer : public MediaCodecBuffer {
public:
- static sp<Codec2Buffer> allocate(
+ static sp<LinearBlockBuffer> allocate(
const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block);
- virtual ~Codec2Buffer() = default;
+ virtual ~LinearBlockBuffer() = default;
C2ConstLinearBlock share();
private:
- Codec2Buffer(
+ LinearBlockBuffer(
const sp<AMessage> &format,
- const sp<ABuffer> &buffer,
+ C2WriteView &&writeView,
const std::shared_ptr<C2LinearBlock> &block);
- Codec2Buffer() = delete;
+ LinearBlockBuffer() = delete;
+ C2WriteView mWriteView;
std::shared_ptr<C2LinearBlock> mBlock;
};
+/**
+ * MediaCodecBuffer implementation wraps around C2ConstLinearBlock.
+ */
+class ConstLinearBlockBuffer : public MediaCodecBuffer {
+public:
+ static sp<ConstLinearBlockBuffer> allocate(
+ const sp<AMessage> &format, const C2ConstLinearBlock &block);
+
+ virtual ~ConstLinearBlockBuffer() = default;
+
+private:
+ ConstLinearBlockBuffer(
+ const sp<AMessage> &format,
+ C2ReadView &&readView);
+ ConstLinearBlockBuffer() = delete;
+
+ C2ReadView mReadView;
+};
+
} // namespace android
#endif // CODEC2_BUFFER_H_
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 11682f8..7c2391e 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -22,7 +22,7 @@
namespace android {
-class DataSource;
+class DataSourceBase;
class String8;
struct ID3 {
@@ -35,7 +35,7 @@
ID3_V2_4,
};
- explicit ID3(const sp<DataSource> &source, bool ignoreV1 = false, off64_t offset = 0);
+ explicit ID3(DataSourceBase *source, bool ignoreV1 = false, off64_t offset = 0);
ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);
~ID3();
@@ -85,8 +85,8 @@
// only valid for IDV2+
size_t mRawSize;
- bool parseV1(const sp<DataSource> &source);
- bool parseV2(const sp<DataSource> &source, off64_t offset);
+ bool parseV1(DataSourceBase *source);
+ bool parseV2(DataSourceBase *source, off64_t offset);
void removeUnsynchronization();
bool removeUnsynchronizationV2_4(bool iTunesHack);
diff --git a/media/libstagefright/include/media/stagefright/InterfaceUtils.h b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
index ceeaf31..568c735 100644
--- a/media/libstagefright/include/media/stagefright/InterfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
@@ -41,7 +41,9 @@
// Creates an IMediaExtractor wrapper to the given MediaExtractor.
sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(
- MediaExtractor *extractor, const sp<RefBase> &plugin);
+ MediaExtractor *extractor,
+ const sp<DataSource> &source,
+ const sp<RefBase> &plugin);
// Creates a MediaSource which wraps the given IMediaSource object.
sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source);
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 4610359..4d2f4f0 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -56,7 +56,7 @@
static void RegisterExtractor(
const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList);
- static MediaExtractor::CreatorFunc sniff(const sp<DataSource> &source,
+ static MediaExtractor::CreatorFunc sniff(DataSourceBase *source,
String8 *mimeType, float *confidence, sp<AMessage> *meta,
sp<ExtractorPlugin> &plugin);
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 78f3a84..22a8210 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -28,7 +28,10 @@
// IMediaExtractor wrapper to the MediaExtractor.
class RemoteMediaExtractor : public BnMediaExtractor {
public:
- static sp<IMediaExtractor> wrap(MediaExtractor *extractor, const sp<RefBase> &plugin);
+ static sp<IMediaExtractor> wrap(
+ MediaExtractor *extractor,
+ const sp<DataSource> &source,
+ const sp<RefBase> &plugin);
virtual ~RemoteMediaExtractor();
virtual size_t countTracks();
@@ -41,15 +44,18 @@
virtual void setUID(uid_t uid);
virtual status_t setMediaCas(const HInterfaceToken &casToken);
virtual const char * name();
- virtual void release();
private:
MediaExtractor *mExtractor;
+ sp<DataSource> mSource;
sp<RefBase> mExtractorPlugin;
MediaAnalyticsItem *mAnalyticsItem;
- explicit RemoteMediaExtractor(MediaExtractor *extractor, const sp<RefBase> &plugin);
+ explicit RemoteMediaExtractor(
+ MediaExtractor *extractor,
+ const sp<DataSource> &source,
+ const sp<RefBase> &plugin);
DISALLOW_EVIL_CONSTRUCTORS(RemoteMediaExtractor);
};
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
index aabbc69..eaf404c 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
@@ -31,6 +31,7 @@
void onPlaybackStateChanged(in Bundle state);
void onPlaylistChanged(in List<Bundle> playlist);
void onPlaylistParamsChanged(in Bundle params);
+ void onPlaybackInfoChanged(in Bundle playbackInfo);
/**
* Called only when the controller is created with service's token.
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 41dfd00..6ee79a0 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -74,6 +74,8 @@
private List<MediaItem2> mPlaylist;
@GuardedBy("mLock")
private PlaylistParams mPlaylistParams;
+ @GuardedBy("mLock")
+ private PlaybackInfo mPlaybackInfo;
// Assignment should be used with the lock hold, but should be used without a lock to prevent
// potential deadlock.
@@ -293,12 +295,6 @@
}
@Override
- public PlaybackInfo getPlaybackInfo_impl() {
- // TODO(jaewan): Implement
- return null;
- }
-
- @Override
public void prepareFromUri_impl(Uri uri, Bundle extras) {
// TODO(jaewan): Implement
}
@@ -413,6 +409,13 @@
}
@Override
+ public PlaybackInfo getPlaybackInfo_impl() {
+ synchronized (mLock) {
+ return mPlaybackInfo;
+ }
+ }
+
+ @Override
public void setPlaylistParams_impl(PlaylistParams params) {
if (params == null) {
throw new IllegalArgumentException("PlaylistParams should not be null!");
@@ -449,6 +452,18 @@
});
}
+ private void pushPlaybackInfoChanges(final PlaybackInfo info) {
+ synchronized (mLock) {
+ mPlaybackInfo = info;
+ }
+ mCallbackExecutor.execute(() -> {
+ if (!mInstance.isConnected()) {
+ return;
+ }
+ mCallback.onPlaybackInfoChanged(info);
+ });
+ }
+
private void pushPlaylistChanges(final List<Bundle> list) {
final List<MediaItem2> playlist = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
@@ -603,6 +618,19 @@
}
@Override
+ public void onPlaybackInfoChanged(Bundle playbackInfo) throws RuntimeException {
+ final MediaController2Impl controller;
+ try {
+ controller = getController();
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Don't fail silently here. Highly likely a bug");
+ return;
+ }
+ controller.pushPlaybackInfoChanges(
+ PlaybackInfoImpl.fromBundle(controller.getContext(), playbackInfo));
+ }
+
+ @Override
public void onConnectionChanged(IMediaSession2 sessionBinder, Bundle commandGroup)
throws RuntimeException {
final MediaController2Impl controller;
diff --git a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
index 54c8d41..77bd334 100644
--- a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
@@ -28,7 +28,7 @@
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSessionService2;
import android.media.SessionToken2;
-import android.media.VolumeProvider;
+import android.media.VolumeProvider2;
import android.media.update.MediaLibraryService2Provider;
import android.os.Bundle;
@@ -68,7 +68,7 @@
private final MediaLibrarySessionCallback mCallback;
public MediaLibrarySessionImpl(Context context,
- MediaPlayerInterface player, String id, VolumeProvider volumeProvider,
+ MediaPlayerInterface player, String id, VolumeProvider2 volumeProvider,
int ratingType, PendingIntent sessionActivity, Executor callbackExecutor,
MediaLibrarySessionCallback callback) {
super(context, player, id, volumeProvider, ratingType, sessionActivity,
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index f820cdc..cde98d2 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -21,15 +21,19 @@
import static android.media.SessionToken2.TYPE_SESSION;
import static android.media.SessionToken2.TYPE_SESSION_SERVICE;
+import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.Manifest.permission;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.MediaController2;
+import android.media.MediaController2.PlaybackInfo;
import android.media.MediaItem2;
import android.media.MediaLibraryService2;
import android.media.MediaMetadata2;
@@ -48,14 +52,13 @@
import android.media.MediaSessionService2;
import android.media.PlaybackState2;
import android.media.SessionToken2;
-import android.media.VolumeProvider;
+import android.media.VolumeProvider2;
import android.media.session.MediaSessionManager;
import android.media.update.MediaSession2Provider;
-import android.media.update.MediaSession2Provider.CommandButtonProvider;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Parcelable;
import android.os.Process;
-import android.os.IBinder;
import android.os.ResultReceiver;
import android.support.annotation.GuardedBy;
import android.text.TextUtils;
@@ -80,11 +83,16 @@
private final SessionCallback mCallback;
private final MediaSession2Stub mSessionStub;
private final SessionToken2 mSessionToken;
+ private final AudioManager mAudioManager;
private final List<PlaybackListenerHolder> mListeners = new ArrayList<>();
@GuardedBy("mLock")
private MediaPlayerInterface mPlayer;
@GuardedBy("mLock")
+ private VolumeProvider2 mVolumeProvider;
+ @GuardedBy("mLock")
+ private PlaybackInfo mPlaybackInfo;
+ @GuardedBy("mLock")
private MyPlaybackListener mListener;
@GuardedBy("mLock")
private PlaylistParams mPlaylistParams;
@@ -103,8 +111,8 @@
* @param ratingType
* @param sessionActivity
*/
- public MediaSession2Impl(Context context, MediaPlayerInterface player,
- String id, VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
+ public MediaSession2Impl(Context context, MediaPlayerInterface player, String id,
+ VolumeProvider2 volumeProvider, int ratingType, PendingIntent sessionActivity,
Executor callbackExecutor, SessionCallback callback) {
// TODO(jaewan): Keep other params.
mInstance = createInstance();
@@ -116,6 +124,7 @@
mCallback = callback;
mCallbackExecutor = callbackExecutor;
mSessionStub = new MediaSession2Stub(this);
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// Infer type from the id and package name.
String libraryService = getServiceName(context, MediaLibraryService2.SERVICE_INTERFACE, id);
@@ -135,6 +144,8 @@
}
setPlayerLocked(player);
+ mVolumeProvider = volumeProvider;
+ mPlaybackInfo = createPlaybackInfo(volumeProvider, player.getAudioAttributes());
// Ask server for the sanity check, and starts
// Sanity check for making session ID unique 'per package' cannot be done in here.
@@ -178,12 +189,8 @@
return serviceName;
}
- // TODO(jaewan): Add explicit release() and do not remove session object with the
- // setPlayer(null). Token can be available when player is null, and
- // controller can also attach to session.
@Override
- public void setPlayer_impl(MediaPlayerInterface player, VolumeProvider volumeProvider)
- throws IllegalArgumentException {
+ public void setPlayer_impl(MediaPlayerInterface player) {
ensureCallingThread();
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
@@ -191,9 +198,37 @@
if (player == mPlayer) {
return;
}
+ PlaybackInfo info =
+ createPlaybackInfo(null /* VolumeProvider */, player.getAudioAttributes());
synchronized (mLock) {
setPlayerLocked(player);
+ mVolumeProvider = null;
+ mPlaybackInfo = info;
}
+ mSessionStub.notifyPlaybackInfoChanged(info);
+ }
+
+ @Override
+ public void setPlayer_impl(MediaPlayerInterface player, VolumeProvider2 volumeProvider)
+ throws IllegalArgumentException {
+ ensureCallingThread();
+ if (player == null) {
+ throw new IllegalArgumentException("player shouldn't be null");
+ }
+ if (volumeProvider == null) {
+ throw new IllegalArgumentException("volumeProvider shouldn't be null");
+ }
+ if (player == mPlayer) {
+ return;
+ }
+
+ PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes());
+ synchronized (mLock) {
+ setPlayerLocked(player);
+ mVolumeProvider = volumeProvider;
+ mPlaybackInfo = info;
+ }
+ mSessionStub.notifyPlaybackInfoChanged(info);
}
private void setPlayerLocked(MediaPlayerInterface player) {
@@ -206,6 +241,29 @@
player.addPlaybackListener(mCallbackExecutor, mListener);
}
+ private PlaybackInfo createPlaybackInfo(VolumeProvider2 volumeProvider, AudioAttributes attrs) {
+ PlaybackInfo info;
+ if (volumeProvider == null) {
+ int stream = attrs == null ? AudioManager.STREAM_MUSIC : attrs.getVolumeControlStream();
+ info = PlaybackInfoImpl.createPlaybackInfo(
+ mContext,
+ PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ attrs,
+ VolumeProvider2.VOLUME_CONTROL_ABSOLUTE,
+ mAudioManager.getStreamMaxVolume(stream),
+ mAudioManager.getStreamVolume(stream));
+ } else {
+ info = PlaybackInfoImpl.createPlaybackInfo(
+ mContext,
+ PlaybackInfo.PLAYBACK_TYPE_REMOTE /* ControlType */,
+ attrs,
+ volumeProvider.getControlType(),
+ volumeProvider.getMaxVolume(),
+ volumeProvider.getCurrentVolume());
+ }
+ return info;
+ }
+
@Override
public void close_impl() {
// Stop system service from listening this session first.
@@ -320,10 +378,6 @@
//////////////////////////////////////////////////////////////////////////////////////
// TODO(jaewan): Implement follows
//////////////////////////////////////////////////////////////////////////////////////
- @Override
- public void setPlayer_impl(MediaPlayerInterface player) {
- // TODO(jaewan): Implement
- }
@Override
public void setAllowedCommands_impl(ControllerInfo controller, CommandGroup commands) {
@@ -1032,7 +1086,7 @@
String mId;
Executor mCallbackExecutor;
C mCallback;
- VolumeProvider mVolumeProvider;
+ VolumeProvider2 mVolumeProvider;
int mRatingType;
PendingIntent mSessionActivity;
@@ -1058,7 +1112,7 @@
mId = "";
}
- public void setVolumeProvider_impl(VolumeProvider volumeProvider) {
+ public void setVolumeProvider_impl(VolumeProvider2 volumeProvider) {
mVolumeProvider = volumeProvider;
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 1f71187..5d3a06e 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -17,6 +17,7 @@
package com.android.media;
import android.content.Context;
+import android.media.MediaController2;
import android.media.MediaItem2;
import android.media.MediaLibraryService2.LibraryRoot;
import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -130,6 +131,7 @@
// Controller may be died prematurely.
}
if (accept) {
+ // TODO(jaewan): We need to send current PlaybackInfo.
// If connection is accepted, notify the current state to the controller.
// It's needed because we cannot call synchronous calls between session/controller.
// Note: We're doing this after the onConnectionChanged(), but there's no guarantee
@@ -390,6 +392,21 @@
}
}
+ public void notifyPlaybackInfoChanged(MediaController2.PlaybackInfo playbackInfo) {
+ final List<ControllerInfo> list = getControllers();
+ for (int i = 0; i < list.size(); i++) {
+ IMediaSession2Callback callbackBinder =
+ ControllerInfoImpl.from(list.get(i)).getControllerBinder();
+ try {
+ callbackBinder.onPlaybackInfoChanged(
+ ((PlaybackInfoImpl) playbackInfo.getProvider()).toBundle());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Controller is gone", e);
+ // TODO(jaewan): What to do when the controller is gone?
+ }
+ }
+ }
+
public void sendCustomCommand(ControllerInfo controller, Command command, Bundle args,
ResultReceiver receiver) {
if (receiver != null && controller == null) {
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index 661e252..46812e7 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -64,7 +64,7 @@
import android.media.update.SessionToken2Provider;
import android.media.update.StaticProvider;
import android.media.update.VideoView2Provider;
-import android.media.update.ViewProvider;
+import android.media.update.ViewGroupProvider;
import android.media.update.VolumeProvider2Provider;
import android.os.Bundle;
import android.os.IInterface;
@@ -205,16 +205,17 @@
}
@Override
- public MediaControlView2Provider createMediaControlView2(
- MediaControlView2 instance, ViewProvider superProvider) {
- return new MediaControlView2Impl(instance, superProvider);
+ public MediaControlView2Provider createMediaControlView2(MediaControlView2 instance,
+ ViewGroupProvider superProvider, ViewGroupProvider privateProvider,
+ @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ return new MediaControlView2Impl(instance, superProvider, privateProvider);
}
@Override
public VideoView2Provider createVideoView2(
- VideoView2 instance, ViewProvider superProvider,
+ VideoView2 instance, ViewGroupProvider superProvider, ViewGroupProvider privateProvider,
@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- return new VideoView2Impl(instance, superProvider, attrs, defStyleAttr, defStyleRes);
+ return new VideoView2Impl(instance, superProvider, privateProvider);
}
@Override
diff --git a/packages/MediaComponents/src/com/android/widget/BaseLayout.java b/packages/MediaComponents/src/com/android/widget/BaseLayout.java
new file mode 100644
index 0000000..fb6471d
--- /dev/null
+++ b/packages/MediaComponents/src/com/android/widget/BaseLayout.java
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+
+package com.android.widget;
+
+import android.graphics.drawable.Drawable;
+import android.media.update.ViewGroupProvider;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewGroup.MarginLayoutParams;
+
+import java.util.ArrayList;
+
+public class BaseLayout extends ViewGroupImpl {
+ private final ViewGroup mInstance;
+ private final ViewGroupProvider mSuperProvider;
+ private final ViewGroupProvider mPrivateProvider;
+
+ private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
+
+ public BaseLayout(ViewGroup instance,
+ ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
+ super(instance, superProvider, privateProvider);
+ mInstance = instance;
+ mSuperProvider = superProvider;
+ mPrivateProvider = privateProvider;
+ }
+
+ @Override
+ public boolean checkLayoutParams_impl(LayoutParams p) {
+ return p instanceof MarginLayoutParams;
+ }
+
+ @Override
+ public LayoutParams generateDefaultLayoutParams_impl() {
+ return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams_impl(AttributeSet attrs) {
+ return new MarginLayoutParams(mInstance.getContext(), attrs);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams_impl(LayoutParams lp) {
+ if (lp instanceof MarginLayoutParams) {
+ return lp;
+ }
+ return new MarginLayoutParams(lp);
+ }
+
+ @Override
+ public void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec) {
+ int count = mInstance.getChildCount();
+
+ final boolean measureMatchParentChildren =
+ View.MeasureSpec.getMode(widthMeasureSpec) != View.MeasureSpec.EXACTLY ||
+ View.MeasureSpec.getMode(heightMeasureSpec) != View.MeasureSpec.EXACTLY;
+ mMatchParentChildren.clear();
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+ int childState = 0;
+
+ for (int i = 0; i < count; i++) {
+ final View child = mInstance.getChildAt(i);
+ if (child.getVisibility() != View.GONE) {
+ mPrivateProvider.measureChildWithMargins_impl(
+ child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+ maxWidth = Math.max(maxWidth,
+ child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
+ maxHeight = Math.max(maxHeight,
+ child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
+ childState = childState | child.getMeasuredState();
+ if (measureMatchParentChildren) {
+ if (lp.width == LayoutParams.MATCH_PARENT ||
+ lp.height == LayoutParams.MATCH_PARENT) {
+ mMatchParentChildren.add(child);
+ }
+ }
+ }
+ }
+
+ // Account for padding too
+ maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground();
+ maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground();
+
+ // Check against our minimum height and width
+ maxHeight = Math.max(maxHeight, mPrivateProvider.getSuggestedMinimumHeight_impl());
+ maxWidth = Math.max(maxWidth, mPrivateProvider.getSuggestedMinimumWidth_impl());
+
+ // Check against our foreground's minimum height and width
+ final Drawable drawable = mInstance.getForeground();
+ if (drawable != null) {
+ maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
+ maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
+ }
+
+ mPrivateProvider.setMeasuredDimension_impl(
+ mInstance.resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+ mInstance.resolveSizeAndState(maxHeight, heightMeasureSpec,
+ childState << View.MEASURED_HEIGHT_STATE_SHIFT));
+
+ count = mMatchParentChildren.size();
+ if (count > 1) {
+ for (int i = 0; i < count; i++) {
+ final View child = mMatchParentChildren.get(i);
+ final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+
+ final int childWidthMeasureSpec;
+ if (lp.width == LayoutParams.MATCH_PARENT) {
+ final int width = Math.max(0, mInstance.getMeasuredWidth()
+ - getPaddingLeftWithForeground() - getPaddingRightWithForeground()
+ - lp.leftMargin - lp.rightMargin);
+ childWidthMeasureSpec = View.MeasureSpec.makeMeasureSpec(
+ width, View.MeasureSpec.EXACTLY);
+ } else {
+ childWidthMeasureSpec = mInstance.getChildMeasureSpec(widthMeasureSpec,
+ getPaddingLeftWithForeground() + getPaddingRightWithForeground() +
+ lp.leftMargin + lp.rightMargin,
+ lp.width);
+ }
+
+ final int childHeightMeasureSpec;
+ if (lp.height == LayoutParams.MATCH_PARENT) {
+ final int height = Math.max(0, mInstance.getMeasuredHeight()
+ - getPaddingTopWithForeground() - getPaddingBottomWithForeground()
+ - lp.topMargin - lp.bottomMargin);
+ childHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
+ height, View.MeasureSpec.EXACTLY);
+ } else {
+ childHeightMeasureSpec = mInstance.getChildMeasureSpec(heightMeasureSpec,
+ getPaddingTopWithForeground() + getPaddingBottomWithForeground() +
+ lp.topMargin + lp.bottomMargin,
+ lp.height);
+ }
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+ }
+ }
+
+ @Override
+ public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
+ final int count = mInstance.getChildCount();
+
+ final int parentLeft = getPaddingLeftWithForeground();
+ final int parentRight = right - left - getPaddingRightWithForeground();
+
+ final int parentTop = getPaddingTopWithForeground();
+ final int parentBottom = bottom - top - getPaddingBottomWithForeground();
+
+ for (int i = 0; i < count; i++) {
+ final View child = mInstance.getChildAt(i);
+ if (child.getVisibility() != View.GONE) {
+ final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+
+ final int width = child.getMeasuredWidth();
+ final int height = child.getMeasuredHeight();
+
+ int childLeft;
+ int childTop;
+
+ childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
+ lp.leftMargin - lp.rightMargin;
+
+ childTop = parentTop + (parentBottom - parentTop - height) / 2 +
+ lp.topMargin - lp.bottomMargin;
+
+ child.layout(childLeft, childTop, childLeft + width, childTop + height);
+ }
+ }
+ }
+
+ @Override
+ public boolean shouldDelayChildPressedState_impl() {
+ return false;
+ }
+
+ private int getPaddingLeftWithForeground() {
+ return mInstance.isForegroundInsidePadding() ? Math.max(mInstance.getPaddingLeft(), 0) :
+ mInstance.getPaddingLeft() + 0;
+ }
+
+ private int getPaddingRightWithForeground() {
+ return mInstance.isForegroundInsidePadding() ? Math.max(mInstance.getPaddingRight(), 0) :
+ mInstance.getPaddingRight() + 0;
+ }
+
+ private int getPaddingTopWithForeground() {
+ return mInstance.isForegroundInsidePadding() ? Math.max(mInstance.getPaddingTop(), 0) :
+ mInstance.getPaddingTop() + 0;
+ }
+
+ private int getPaddingBottomWithForeground() {
+ return mInstance.isForegroundInsidePadding() ? Math.max(mInstance.getPaddingBottom(), 0) :
+ mInstance.getPaddingBottom() + 0;
+ }
+}
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 138232e..1cdaaee 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -21,8 +21,10 @@
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.media.update.MediaControlView2Provider;
-import android.media.update.ViewProvider;
+import android.media.update.ViewGroupProvider;
import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -46,11 +48,10 @@
import java.util.List;
import java.util.Locale;
-public class MediaControlView2Impl implements MediaControlView2Provider {
+public class MediaControlView2Impl extends BaseLayout implements MediaControlView2Provider {
private static final String TAG = "MediaControlView2";
private final MediaControlView2 mInstance;
- private final ViewProvider mSuperProvider;
static final String ARGUMENT_KEY_FULLSCREEN = "fullScreen";
@@ -63,7 +64,7 @@
private static final int REWIND_TIME_MS = 10000;
private static final int FORWARD_TIME_MS = 30000;
- private final AccessibilityManager mAccessibilityManager;
+ private AccessibilityManager mAccessibilityManager;
private MediaController mController;
private MediaController.TransportControls mControls;
@@ -113,10 +114,14 @@
private MediaRouteButton mRouteButton;
private MediaRouteSelector mRouteSelector;
- public MediaControlView2Impl(
- MediaControlView2 instance, ViewProvider superProvider) {
+ public MediaControlView2Impl(MediaControlView2 instance,
+ ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
+ super(instance, superProvider, privateProvider);
mInstance = instance;
- mSuperProvider = superProvider;
+ }
+
+ @Override
+ public void initialize(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
mAccessibilityManager = AccessibilityManager.getInstance(mInstance.getContext());
// Inflate MediaControlView2 from XML
@@ -144,11 +149,6 @@
}
@Override
- public boolean isShowing_impl() {
- return (mInstance.getVisibility() == View.VISIBLE) ? true : false;
- }
-
- @Override
public void setButtonVisibility_impl(int button, int visibility) {
switch (button) {
case MediaControlView2.BUTTON_PLAY_PAUSE:
@@ -233,39 +233,6 @@
}
@Override
- public void onVisibilityAggregated_impl(boolean invisible) {
- int visibility = mInstance.getVisibility();
- if (mCurrentVisibility != visibility) {
- mInstance.setVisibility(visibility);
- mCurrentVisibility = visibility;
-
- if (visibility == View.VISIBLE) {
- setProgress();
- disableUnsupportedButtons();
- // cause the progress bar to be updated even if mShowing
- // was already true. This happens, for example, if we're
- // paused with the progress bar showing the user hits play.
- mInstance.post(mShowProgress);
- resetFadeOutRunnable();
- } else if (visibility == View.GONE) {
- mInstance.removeCallbacks(mShowProgress);
- // Remove existing call to mFadeOut to avoid from being called later.
- mInstance.removeCallbacks(mFadeOut);
- }
- }
- }
-
- @Override
- public void onAttachedToWindow_impl() {
- mSuperProvider.onAttachedToWindow_impl();
- }
-
- @Override
- public void onDetachedFromWindow_impl() {
- mSuperProvider.onDetachedFromWindow_impl();
- }
-
- @Override
public CharSequence getAccessibilityClassName_impl() {
return MediaControlView2.class.getName();
}
@@ -283,12 +250,9 @@
}
@Override
- public void onFinishInflate_impl() {
- mSuperProvider.onFinishInflate_impl();
- }
-
- @Override
public void setEnabled_impl(boolean enabled) {
+ super.setEnabled_impl(enabled);
+
if (mPlayPauseButton != null) {
mPlayPauseButton.setEnabled(enabled);
}
@@ -308,7 +272,31 @@
mProgress.setEnabled(enabled);
}
disableUnsupportedButtons();
- mSuperProvider.setEnabled_impl(enabled);
+ }
+
+ @Override
+ public void onVisibilityAggregated_impl(boolean invisible) {
+ super.onVisibilityAggregated_impl(invisible);
+
+ int visibility = mInstance.getVisibility();
+ if (mCurrentVisibility != visibility) {
+ mInstance.setVisibility(visibility);
+ mCurrentVisibility = visibility;
+
+ if (visibility == View.VISIBLE) {
+ setProgress();
+ disableUnsupportedButtons();
+ // cause the progress bar to be updated even if mShowing
+ // was already true. This happens, for example, if we're
+ // paused with the progress bar showing the user hits play.
+ mInstance.post(mShowProgress);
+ resetFadeOutRunnable();
+ } else if (visibility == View.GONE) {
+ mInstance.removeCallbacks(mShowProgress);
+ // Remove existing call to mFadeOut to avoid from being called later.
+ mInstance.removeCallbacks(mFadeOut);
+ }
+ }
}
public void setRouteSelector(MediaRouteSelector selector) {
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index 7218150..9f207b1 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -39,17 +39,16 @@
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.media.update.VideoView2Provider;
-import android.media.update.ViewProvider;
+import android.media.update.ViewGroupProvider;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.widget.FrameLayout.LayoutParams;
+import android.view.ViewGroup.LayoutParams;
import android.widget.MediaControlView2;
import android.widget.VideoView2;
@@ -67,12 +66,12 @@
import java.util.Map;
import java.util.concurrent.Executor;
-public class VideoView2Impl implements VideoView2Provider, VideoViewInterface.SurfaceListener {
+public class VideoView2Impl extends BaseLayout
+ implements VideoView2Provider, VideoViewInterface.SurfaceListener {
private static final String TAG = "VideoView2";
private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG);
private final VideoView2 mInstance;
- private final ViewProvider mSuperProvider;
private static final int STATE_ERROR = -1;
private static final int STATE_IDLE = 0;
@@ -82,7 +81,7 @@
private static final int STATE_PAUSED = 4;
private static final int STATE_PLAYBACK_COMPLETED = 5;
- private final AudioManager mAudioManager;
+ private AudioManager mAudioManager;
private AudioAttributes mAudioAttributes;
private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
@@ -127,11 +126,14 @@
// Refer: https://docs.google.com/document/d/1nzAfns6i2hJ3RkaUre3QMT6wsDedJ5ONLiA_OOBFFX8/edit
private float mFallbackSpeed; // keep the original speed before 'pause' is called.
- public VideoView2Impl(VideoView2 instance, ViewProvider superProvider,
- @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public VideoView2Impl(VideoView2 instance,
+ ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
+ super(instance, superProvider, privateProvider);
mInstance = instance;
- mSuperProvider = superProvider;
+ }
+ @Override
+ public void initialize(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
mVideoWidth = 0;
mVideoHeight = 0;
mSpeed = 1.0f;
@@ -150,7 +152,6 @@
mSurfaceView = new VideoSurfaceView(mInstance.getContext());
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
- params.gravity = Gravity.CENTER;
mTextureView.setLayoutParams(params);
mSurfaceView.setLayoutParams(params);
mTextureView.setSurfaceListener(this);
@@ -397,7 +398,7 @@
@Override
public void onAttachedToWindow_impl() {
- mSuperProvider.onAttachedToWindow_impl();
+ super.onAttachedToWindow_impl();
// Create MediaSession
mMediaSession = new MediaSession(mInstance.getContext(), "VideoView2MediaSession");
@@ -412,8 +413,8 @@
@Override
public void onDetachedFromWindow_impl() {
- Log.e(TAG, ".... Debugging. onDetachedFromWindow_impl()");
- mSuperProvider.onDetachedFromWindow_impl();
+ super.onDetachedFromWindow_impl();
+
mMediaSession.release();
mMediaSession = null;
mMediaController = null;
@@ -434,7 +435,8 @@
&& isInPlaybackState() && mMediaControlView != null) {
toggleMediaControlViewVisibility();
}
- return mSuperProvider.onTouchEvent_impl(ev);
+
+ return super.onTouchEvent_impl(ev);
}
@Override
@@ -443,17 +445,8 @@
&& isInPlaybackState() && mMediaControlView != null) {
toggleMediaControlViewVisibility();
}
- return mSuperProvider.onTrackballEvent_impl(ev);
- }
- @Override
- public void onFinishInflate_impl() {
- mSuperProvider.onFinishInflate_impl();
- }
-
- @Override
- public void setEnabled_impl(boolean enabled) {
- mSuperProvider.setEnabled_impl(enabled);
+ return super.onTrackballEvent_impl(ev);
}
///////////////////////////////////////////////////
@@ -700,7 +693,7 @@
}
private void toggleMediaControlViewVisibility() {
- if (mMediaControlView.isShowing()) {
+ if (mMediaControlView.getVisibility() == View.VISIBLE) {
mMediaControlView.setVisibility(View.GONE);
} else {
mMediaControlView.setVisibility(View.VISIBLE);
diff --git a/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java b/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
new file mode 100644
index 0000000..8598bb2
--- /dev/null
+++ b/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+package com.android.widget;
+
+import android.media.update.ViewGroupProvider;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+public abstract class ViewGroupImpl implements ViewGroupProvider {
+ private final ViewGroupProvider mSuperProvider;
+
+ public ViewGroupImpl(ViewGroup instance,
+ ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
+ mSuperProvider = superProvider;
+ }
+
+ @Override
+ public void onAttachedToWindow_impl() {
+ mSuperProvider.onAttachedToWindow_impl();
+ }
+
+ @Override
+ public void onDetachedFromWindow_impl() {
+ mSuperProvider.onDetachedFromWindow_impl();
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName_impl() {
+ return mSuperProvider.getAccessibilityClassName_impl();
+ }
+
+ @Override
+ public boolean onTouchEvent_impl(MotionEvent ev) {
+ return mSuperProvider.onTouchEvent_impl(ev);
+ }
+
+ @Override
+ public boolean onTrackballEvent_impl(MotionEvent ev) {
+ return mSuperProvider.onTrackballEvent_impl(ev);
+ }
+
+ @Override
+ public void onFinishInflate_impl() {
+ mSuperProvider.onFinishInflate_impl();
+ }
+
+ @Override
+ public void setEnabled_impl(boolean enabled) {
+ mSuperProvider.setEnabled_impl(enabled);
+ }
+
+ @Override
+ public void onVisibilityAggregated_impl(boolean isVisible) {
+ mSuperProvider.onVisibilityAggregated_impl(isVisible);
+ }
+
+ @Override
+ public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
+ mSuperProvider.onLayout_impl(changed, left, top, right, bottom);
+ }
+
+ @Override
+ public void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec) {
+ mSuperProvider.onMeasure_impl(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ public int getSuggestedMinimumWidth_impl() {
+ return mSuperProvider.getSuggestedMinimumWidth_impl();
+ }
+
+ @Override
+ public int getSuggestedMinimumHeight_impl() {
+ return mSuperProvider.getSuggestedMinimumHeight_impl();
+ }
+
+ @Override
+ public void setMeasuredDimension_impl(int measuredWidth, int measuredHeight) {
+ mSuperProvider.setMeasuredDimension_impl(measuredWidth, measuredHeight);
+ }
+
+ @Override
+ public boolean checkLayoutParams_impl(ViewGroup.LayoutParams p) {
+ return mSuperProvider.checkLayoutParams_impl(p);
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateDefaultLayoutParams_impl() {
+ return mSuperProvider.generateDefaultLayoutParams_impl();
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams_impl(AttributeSet attrs) {
+ return mSuperProvider.generateLayoutParams_impl(attrs);
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams_impl(ViewGroup.LayoutParams lp) {
+ return mSuperProvider.generateLayoutParams_impl(lp);
+ }
+
+ @Override
+ public boolean shouldDelayChildPressedState_impl() {
+ return mSuperProvider.shouldDelayChildPressedState_impl();
+ }
+
+ @Override
+ public void measureChildWithMargins_impl(View child,
+ int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
+ mSuperProvider.measureChildWithMargins_impl(child,
+ parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
+ }
+}
diff --git a/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java b/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
index 38475a8..4cd8177 100644
--- a/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
@@ -128,6 +128,13 @@
}
@Override
+ public void onPlaybackInfoChanged(MediaController2.PlaybackInfo info) {
+ if (mCallbackProxy != null) {
+ mCallbackProxy.onPlaybackInfoChanged(info);
+ }
+ }
+
+ @Override
public void onCustomCommand(Command command, Bundle args, ResultReceiver receiver) {
super.onCustomCommand(command, args, receiver);
mCallbackProxy.onCustomCommand(command, args, receiver);
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
index ff8c2b7..43a6c2c 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
@@ -16,10 +16,16 @@
package android.media;
+import static android.media.AudioAttributes.CONTENT_TYPE_MUSIC;
+import static android.media.TestUtils.ensurePlaylistParamsModeEquals;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
-import static android.media.TestUtils.ensurePlaylistParamsModeEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.MediaSession2.Builder;
@@ -36,19 +42,17 @@
import android.support.test.runner.AndroidJUnit4;
import android.text.TextUtils;
-import java.util.ArrayList;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import static org.junit.Assert.*;
-
/**
* Tests {@link MediaSession2}.
*/
@@ -105,6 +109,48 @@
}
@Test
+ public void testSetPlayerWithVolumeProvider() throws Exception {
+ MockPlayer player = new MockPlayer(0);
+ AudioAttributes attrs = new AudioAttributes.Builder()
+ .setContentType(CONTENT_TYPE_MUSIC)
+ .build();
+ player.setAudioAttributes(attrs);
+
+ final int maxVolume = 100;
+ final int currentVolume = 23;
+ final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ VolumeProvider2 volumeProvider =
+ new VolumeProvider2(mContext, volumeControlType, maxVolume, currentVolume) { };
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final TestControllerCallbackInterface callback = new TestControllerCallbackInterface() {
+ @Override
+ public void onPlaybackInfoChanged(MediaController2.PlaybackInfo info) {
+ assertEquals(MediaController2.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
+ info.getPlaybackType());
+ assertEquals(attrs, info.getAudioAttributes());
+ assertEquals(volumeControlType, info.getPlaybackType());
+ assertEquals(maxVolume, info.getMaxVolume());
+ assertEquals(currentVolume, info.getCurrentVolume());
+ latch.countDown();
+ }
+ };
+
+ final MediaController2 controller = createController(mSession.getToken(), true, callback);
+ assertNull(controller.getPlaybackInfo());
+
+ mSession.setPlayer(player, volumeProvider);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+ MediaController2.PlaybackInfo infoOut = controller.getPlaybackInfo();
+ assertEquals(MediaController2.PlaybackInfo.PLAYBACK_TYPE_REMOTE, infoOut.getPlaybackType());
+ assertEquals(attrs, infoOut.getAudioAttributes());
+ assertEquals(volumeControlType, infoOut.getPlaybackType());
+ assertEquals(maxVolume, infoOut.getMaxVolume());
+ assertEquals(currentVolume, infoOut.getCurrentVolume());
+ }
+
+ @Test
public void testPlay() throws Exception {
sHandler.postAndSync(() -> {
mSession.play();
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java b/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java
index 5d94b17..513fa29 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java
@@ -63,6 +63,7 @@
// Add methods in ControllerCallback/BrowserCallback that you want to test.
default void onPlaylistChanged(List<MediaItem2> playlist) {}
default void onPlaylistParamsChanged(MediaSession2.PlaylistParams params) {}
+ default void onPlaybackInfoChanged(MediaController2.PlaybackInfo info) {}
// Currently empty. Add methods in ControllerCallback/BrowserCallback that you want to test.
default void onPlaybackStateChanged(PlaybackState2 state) { }
@@ -241,6 +242,13 @@
mCallbackProxy.onPlaylistParamsChanged(params);
}
}
+
+ @Override
+ public void onPlaybackInfoChanged(MediaController2.PlaybackInfo info) {
+ if (mCallbackProxy != null) {
+ mCallbackProxy.onPlaybackInfoChanged(info);
+ }
+ }
}
public class TestMediaController extends MediaController2 implements TestControllerInterface {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 592273e..e7140c2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1984,7 +1984,7 @@
for (size_t i = 0; i < fakeNum; i++) {
struct audio_microphone_characteristic_t characteristics;
sprintf(characteristics.device_id, "microphone:%zu", i);
- characteristics.type = fakeTypes[i];
+ characteristics.device = fakeTypes[i];
sprintf(characteristics.address, "");
characteristics.location = AUDIO_MICROPHONE_LOCATION_MAINBODY;
characteristics.group = 0;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 14d7e2e..24d862f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7051,7 +7051,7 @@
// Fake data
struct audio_microphone_characteristic_t characteristic;
sprintf(characteristic.device_id, "builtin_mic");
- characteristic.type = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ characteristic.device = AUDIO_DEVICE_IN_BUILTIN_MIC;
sprintf(characteristic.address, "");
characteristic.location = AUDIO_MICROPHONE_LOCATION_MAINBODY;
characteristic.group = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 9ba8bb7..324201b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2400,7 +2400,7 @@
Vector<camera3_stream_t*> streams;
streams.setCapacity(config.num_streams);
- std::vector<uint32_t> outBufSizes(mOutputStreams.size(), 0);
+ std::vector<uint32_t> bufferSizes(config.num_streams, 0);
if (mInputStream != NULL) {
@@ -2435,7 +2435,9 @@
if (outputStream->format == HAL_PIXEL_FORMAT_BLOB &&
outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
- outBufSizes[i] = static_cast<uint32_t>(
+ size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
+ // always occupy the initial entry.
+ bufferSizes[k] = static_cast<uint32_t>(
getJpegBufferSize(outputStream->width, outputStream->height));
}
}
@@ -2446,7 +2448,7 @@
// max_buffers, usage, priv fields.
const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
- res = mInterface->configureStreams(sessionBuffer, &config, outBufSizes);
+ res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
sessionParams.unlock(sessionBuffer);
if (res == BAD_VALUE) {
@@ -3504,7 +3506,7 @@
}
status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
- camera3_stream_configuration *config, const std::vector<uint32_t>& outputBufferSizes) {
+ camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
ATRACE_NAME("CameraHal::configureStreams");
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
@@ -3545,7 +3547,7 @@
dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
dst3_4.v3_2 = dst3_2;
- dst3_4.bufferSize = outputBufferSizes[i];
+ dst3_4.bufferSize = bufferSizes[i];
if (src->physical_camera_id != nullptr) {
dst3_4.physicalCameraId = src->physical_camera_id;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ccd9d7a..12cb6b4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -283,7 +283,7 @@
/*out*/ camera_metadata_t **requestTemplate);
status_t configureStreams(const camera_metadata_t *sessionParams,
/*inout*/ camera3_stream_configuration *config,
- const std::vector<uint32_t>& outputBufferSizes);
+ const std::vector<uint32_t>& bufferSizes);
status_t processCaptureRequest(camera3_capture_request_t *request);
status_t processBatchCaptureRequests(
std::vector<camera3_capture_request_t*>& requests,