summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2013-07-25 17:33:47 +0800
committerSteve Kondik <steve@cyngn.com>2015-10-28 16:44:24 -0700
commitcd54d7de1cfc9ddf599abc0c2e9308b96b2b6a76 (patch)
treeddf96d46ff83e739a6b5c5e779482e63a807de84
parent4440ef8efc77d1bd7838885e83d41e54deb5a3b8 (diff)
downloadframeworks_av-cd54d7de1cfc9ddf599abc0c2e9308b96b2b6a76.zip
frameworks_av-cd54d7de1cfc9ddf599abc0c2e9308b96b2b6a76.tar.gz
frameworks_av-cd54d7de1cfc9ddf599abc0c2e9308b96b2b6a76.tar.bz2
libstagefright: Extended media support via FFMPEG
* Original work by Michael Chen - https://github.com/omxcodec * Kitkat port by Chih-Wei Huang / Android X86 project * Additional fixes by Arcee and Cyanogen * High resolution support by Cyanogen * Lollipop port and refactoring by Cyanogen * Marshmallow port and refactoring by Cyanogen ------ libstagefright: add null checking to addPlugin libstagefright: fix error handling of dlsym() According 'man dlsym', a NULL return from dlsym() doesn't indicate an error. The correct way to test for an error is to call dlerror() to clear any old error conditions, then call dlsym(), and then call dlerror() again to check whether its return value is not NULL. libstagefright: add more media mimetypes This is the first step to add the ffmpeg plugins. libstagefright: add ExtractorPlugin The patch allows to load an ExtractorPlugin to extend the functions of DataSource::sniff and MediaExtractor. A plugin has to implement a C function getExtractorPlugin to fill the MediaExtractor::Plugin struct. The filename of the plugin could be specified by the media.stagefright.extractor-plugin property. Change-Id: I995a37a4f1ab4bba6ca3c24c7001a27a1e3ccb90 FLACExtractor: Add more sample rates support In FLACExtractor.cpp, it has function to check file's sample rate. If the input sample rate is not in its list, it will return "unsupported sample rate" issue. Modify code to make other sample rates (100,1k,42k,46k) pass the check Issue: AXIA-1441 Change-Id: I48f91119275560ec6d00feb0dedc70d10aa55262 Signed-off-by: Xiaobing Feng <xiaobing.feng@windriver.com> Signed-off-by: Matt Gumbel <matthew.k.gumbel@intel.com> libstagefright: add ffmpeg components libstagefright: add more decoders Add support for wma, wmv, ra, ape, dts decoders. Change-Id: Iaf48a806aa0cef7d9bcb848383fc3d778c8bd248 libstagefright: allow to use the extended extractor in priority If the meta contains the string "extended-extractor-use", use the extended extractor first. add support for rv20, rv30 add ffmpeg heuristic decoder Change-Id: I5eed11b563ca7f15d44bacfb795d6f3da08ab883 add HEVC(H.265) decoder and cleanup Squashed the following commits of branch cm_maguro-10.1 from https://github.com/omxcodec/android_frameworks_av.git by Michael Chen <omxcodec@gmail.com> defb904 remove MEDIA_MIMETYPE_AUDIO_MP2 8036958 add fetchUriFromFd func to get file name 91bc7d5 fix videoCompressionFormatString and audioCodingTypeString funcs f03069f reset FRAME_DROP_FREQ to 0 718b99a add HEVC(H.265) decoder 84f8bf6 cleanup f026c93 cleanup 440614a add debug info Change-Id: Ie75db0778f633357e2280aef6d47a0fa3beb823e AwesomePlayer: use AwesomeLocalRenderer for OMX.ffmpeg.* components stagefright: Remove duplicate types from QC media defs Change-Id: I50ecafe79a2985d0868a1ac82464d6ca448aa2c5 Conflicts: media/libstagefright/ExtendedMediaDefs.cpp media/libstagefright/OMXCodec.cpp libstagefright: Re-introduce a QCOM_HARDWARE ifdef after the FFMPEG commit Fixes a build error on non QCOM hardware. Change-Id: I4a4268b351d0d8bf748dd03ccea0fbab20ed4314 DataSource: Split off ffmpeg sniffer to a second pass, and only if necessary ffmpeg's sniffer is intended as a grab-all-that-doesn't-work-elsewhere extractor. Unfortunately, this causes two issues: - As written, it requires ffmpeg to whitelist any extractors supported by stagefright, or else it will blindly override them. This has codebase sync issues, as shown by the VP9 and WAV accidental overrides - It imposes an in-depth analysis of _all_ media, even that which we want to be processed quickly by shipping stagefright plugins (hardware or not). This is mostly noticeable in network streams and thumbnail generation. This patch moves FFmpegExtractor to an independent sniffer queue, and it only invokes it when the regular MediaExtractor hits 1 of 3 conditions: 1 - The confidence in the identified container type is low 2 - No container is identified at all 3 - A video container was found by other extractors, but only 1 stream (audio or video) was identified. Change-Id: Ib96ff4f6bc06223fe0e819a57560d3c872a79ddd stagefright: OMX.ffmpeg.* are software decoders, ensure they're treated as such Wherever the component name for OMX.google soft decoders is used to identify a software-based component, do the same for ffmpeg. Things like memory management and window buffers care about this. Change-Id: Ib83561936c7383e8726edb073cea9d78f7d1312f libstagefright: Don't invoke FFMPEG for MP3 Change-Id: Ia30d25d1a994328827f14a286661cd2e1eaa1181 stagefright: Fix audio codec fallthru * We shouldn't return an error from setAudioFormat unless it's really an error since fallthru is necessary. * We don't even need to do this, since the component name is checked before calling into mm-parser or FFMPEG. * Fixes Vorbis decoding after FFMPEG patch. Change-Id: I4871c62044c6693e5698119dee3a10c20c26e2c7 stagefright: Fix codec lookup bugs on NuPlayer * Fix use of WMA/WMV software codecs * Fix mpeg2 software codec name * Don't override the component name in ACodec. This actually breaks stuff because the format isn't available in the kInit message. Change-Id: I93c292e039de5f24c2ccbd6ae2242b06d28fe518 stagefright: Cleanup and improve format parsing * Move FFMPEG-specific exceptions to FFMPEGSoftCodec * Add handling for AAC MAIN profile * Use the new OMX_AUDIO_CodingAndroidAC3 to handle AC3 Change-Id: Ibb806cd2b9dd23dc1e1b2c862fcde40605023a49 stagefright: Keep track of the bit width in the RAW codec * We need this to push 24-bit PCM around Stagefright and OMX Change-Id: Ic94ec972162a01545d5dd0ad0bf3eb6c6731f42e stagefright: Adjust confidence threshold for extended sniffers * Some sniffers return 0.2 for cases where they only find an audio track in some containers. * Change the comparison to also examine files right on this threshold. * This allows us to score ONE FUCKING HUNDRED PERCENT on the Antutu Video Test \o/ Change-Id: I78b6ab8a634771e0e290f669801f5b08d6a32a51 stagefright: Fix FFMPEG catchall decoders * Get this metadata properly flowing * Allows us to play tracks such as Apple Lossless :) Change-Id: I2990b30eef5b672da339d24444424c61a43b85c2 stagefright: Fix metadata/message conversion issues * Remove duplication of code between ExtendedCodec and FFMPEGSoftCodec, just call into ExtendedCodec and properly ifdef QCOM-only parts. * Fix CSD not being converted when AV_ENHANCEMENTS wasn't set- this was breaking the software video codecs on Hammerhead. Change-Id: I9cd4316ce19b15baabf12b78b992498ce48e2697 Fix compile error after I9cd4316ce19b15baabf12b78b992498ce48e2697 frameworks/av/media/libstagefright/ExtendedCodec.cpp:1187:1: error: expected '}' at end of input Change-Id: I7d75e69160f794b177f4235f4a6bb5a188dc0d08 stagefright: Fix AC3 playback * Skip setupAC3Codec in ACodec for non-Google components. Change-Id: I5090485ba020f7ad1c0962fc977e38675b4c8314 stagefright: Guard against crash with mismatched codecs * Return unsupported error if WMV file can't be scanned. Change-Id: Ia4a1ac7a299990f8b9c05a93736cb2fa9d0ee965 stagefright: Correct ifdeffage of some QC codecs Change-Id: Ie8cc7287967b84e09941283559ca542efd928d91 stagefright: Create native window for FFMPEG software codecs Change-Id: I178f334f1fa1ea9edc6898fb61e72902c2cb2651 stagefright: Don't ever try to use extended sniffers on DRM * This can cause long retry intervals during key exchange. Don't do it! Change-Id: Id9a87dcbe43cd0cc9919fe07f0a963e087baccad stagefright: Be more tolerant of missing metadata for FFMPEG codecs * If these codecs are instantiated programatically and required metadata isn't sent, just set some defaults instead of crashing on an assert. * This fixes testAllNonTunneledVideoCodecsSupportFlexibleYUV in MR1 CTS Change-Id: I69bf6105a1be529298de574bd5d3b6813e7a4e8f stagefright: Fix issues with software decoders * Fix MKV thumbnails * Fix VC1 thumbnails * Fix FFMPEG thumbnails * Fix trial decoder * Fix edge cases with WMV3/VC1 playback * Fix a state issue which caused some codecs to get wrong configuration Change-Id: I09599166aa24bcff53f91e43de096c4fad8ca7ad stagefright: ffmpeg: Slightly raise the threshold for the ffmpeg scanner 0.2 is the success value for the OMX.google soft audio sniffers, which was making ffmpeg own the unpacking of those streams needlessly. Fixes CYNGNOS-282 Change-Id: I75f50ed838cb8af9acdf99aa284b80a070555284 stagefright: Add support for loading a custom OMXPlugin * To facilitate moving the stagefright-plugins glue out of the framework, support is added to OMXMaster to load multiple external plugins besides internal/vendor versions. * This is currently limited to one plugin, defined by the "mm.sf.omx-plugin" system property. The code will allow any number of libraries to be loaded, though. * Should also be useful for nonstandard vendor implementations too. Change-Id: I27d7e16ad56baa17754d8ea47a8c608a0d73d6f1 stagefright: Move a bunch of FFMPEG stuff out of here * Get rid of some of the glue code for stagefright-plugins and use the new extension header and plugin. * Still a bunch of TODOs on this, but it works. Change-Id: If07d3213952b624d48035e5f58ad883b2a4049b0 stagefright: Remove deprecated FFMPEG config Change-Id: I1fcdb4eeba72e2420493b89ddd6fc718d170ced7 stagefright: Support for 24-bit audio in StageFright * Plumb bit depth thru ACodec and OMX * Add support for 24-bit PCM offload in NuPlayer on QC devices * Use new AudioFlinger features for mixing multi formats without offload * Clean up a bunch of code Change-Id: I018d3a995b63450a38c6c43eaa37c86be30fd893 nuplayer: Fix PCM offload turning on all the time * Remove the extra condition, since this will be set even if PCM offload was denied. Change-Id: I8f33ef68562d8e057e7a86c5ae6187d0049bf3aa stagefright: Cleanup of PCM offload checks * Put the checks in a single place. Change-Id: I2d0d5b542593896e78bf989296de1a1d1e3a4963 stagefright: Add bit-depth plumbing for new formats Change-Id: I13cfd75e4b4819543b64babf20cc9af57ea2978f nuplayer: Fix bitrate propagation * We use "bitrate" rather than "bit-rate". Change-Id: I4699194e3e3f7ef55b4eb554f5de7a6b5f6b80ce libstagefright: Implement fallback mechanism to SW decoder Implement fallback mechanism to software decoder when hardware decoder configuration fails in ACodec Change-Id: Idf4c445942b03e28b264c91a20e69d52224727bd
-rw-r--r--include/media/stagefright/ACodec.h11
-rw-r--r--include/media/stagefright/DataSource.h4
-rw-r--r--include/media/stagefright/FFMPEGSoftCodec.h133
-rw-r--r--include/media/stagefright/FileSource.h6
-rw-r--r--include/media/stagefright/MediaDefs.h35
-rw-r--r--include/media/stagefright/MediaExtractor.h15
-rw-r--r--include/media/stagefright/MetaData.h50
-rw-r--r--media/libavextensions/mediaplayerservice/AVNuUtils.cpp60
-rw-r--r--media/libavextensions/stagefright/AVUtils.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/Android.mk3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp10
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp15
-rw-r--r--media/libstagefright/ACodec.cpp168
-rw-r--r--media/libstagefright/Android.mk4
-rw-r--r--media/libstagefright/DataSource.cpp68
-rw-r--r--media/libstagefright/FFMPEGSoftCodec.cpp1149
-rw-r--r--media/libstagefright/FileSource.cpp16
-rw-r--r--media/libstagefright/MediaCodec.cpp3
-rw-r--r--media/libstagefright/MediaDefs.cpp28
-rw-r--r--media/libstagefright/MediaExtractor.cpp26
-rw-r--r--media/libstagefright/OMXClient.cpp1
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp6
-rw-r--r--media/libstagefright/Utils.cpp28
-rw-r--r--media/libstagefright/codecs/raw/SoftRaw.cpp6
-rw-r--r--media/libstagefright/codecs/raw/SoftRaw.h1
-rw-r--r--media/libstagefright/include/AwesomePlayer.h1
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp13
-rw-r--r--services/audioflinger/AudioMixer.h1
28 files changed, 1799 insertions, 68 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index a346e2b..2e621fe 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -28,6 +28,8 @@
#include <media/stagefright/SkipCutBuffer.h>
#include <OMX_Audio.h>
+#include <system/audio.h>
+
#define TRACK_BUFFER_TIMING 0
namespace android {
@@ -345,9 +347,11 @@ protected:
int32_t maxOutputChannelCount, const drcParams_t& drc,
int32_t pcmLimiterEnable);
- status_t setupAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
+ status_t setupAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate,
+ int32_t bitsPerSample = 16);
- status_t setupEAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
+ status_t setupEAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate,
+ int32_t bitsPerSample = 16);
status_t selectAudioPortFormat(
OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat);
@@ -359,7 +363,8 @@ protected:
bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel);
status_t setupRawAudioFormat(
- OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels,
+ int32_t bitsPerSample = 16);
status_t setPriority(int32_t priority);
status_t setOperatingRate(float rateFloat, bool isVideo);
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index de31ff0..56abe71 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -62,8 +62,11 @@ public:
private:
Mutex mSnifferMutex;
List<SnifferFunc> mSniffers;
+ List<SnifferFunc> mExtraSniffers;
List<SnifferFunc>::iterator extendedSnifferPosition;
+ void registerSnifferPlugin();
+
Sniffer(const Sniffer &);
Sniffer &operator=(const Sniffer &);
};
@@ -145,6 +148,7 @@ protected:
sp<Sniffer> mSniffer;
static void RegisterSniffer_l(SnifferFunc func);
+ static void RegisterSnifferPlugin();
DataSource(const DataSource &);
DataSource &operator=(const DataSource &);
diff --git a/include/media/stagefright/FFMPEGSoftCodec.h b/include/media/stagefright/FFMPEGSoftCodec.h
new file mode 100644
index 0000000..83373d0
--- /dev/null
+++ b/include/media/stagefright/FFMPEGSoftCodec.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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 FFMPEG_SOFT_CODEC_H_
+#define FFMPEG_SOFT_CODEC_H_
+
+#include <media/IOMX.h>
+#include <media/MediaCodecInfo.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <media/stagefright/MetaData.h>
+
+#include <OMX_Audio.h>
+#include <OMX_Video.h>
+
+namespace android {
+
+struct FFMPEGSoftCodec {
+
+ enum {
+ kPortIndexInput = 0,
+ kPortIndexOutput = 1
+ };
+
+ static void convertMessageToMetaDataFF(
+ const sp<AMessage> &msg, sp<MetaData> &meta);
+
+ static void convertMetaDataToMessageFF(
+ const sp<MetaData> &meta, sp<AMessage> *format);
+
+ static const char* overrideComponentName(
+ uint32_t quirks, const sp<MetaData> &meta,
+ const char *mime, bool isEncoder);
+
+ static void overrideComponentName(
+ uint32_t quirks, const sp<AMessage> &msg,
+ AString* componentName, AString* mime,
+ int32_t isEncoder);
+
+ static status_t setSupportedRole(
+ const sp<IOMX> &omx, IOMX::node_id node,
+ bool isEncoder, const char *mime);
+
+ static status_t setAudioFormat(
+ const sp<AMessage> &msg, const char* mime,
+ sp<IOMX> OMXhandle, IOMX::node_id nodeID);
+
+ static status_t setVideoFormat(
+ const sp<AMessage> &msg, const char* mime,
+ sp<IOMX> OMXhandle,IOMX::node_id nodeID,
+ bool isEncoder, OMX_VIDEO_CODINGTYPE *compressionFormat);
+
+ static status_t getAudioPortFormat(
+ OMX_U32 portIndex, int coding,
+ sp<AMessage> &notify, sp<IOMX> OMXhandle, IOMX::node_id nodeID);
+
+ static status_t getVideoPortFormat(
+ OMX_U32 portIndex, int coding,
+ sp<AMessage> &notify, sp<IOMX> OMXhandle, IOMX::node_id nodeID);
+
+private:
+ static const char* getMsgKey(int key);
+
+ static status_t setWMVFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setRVFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setFFmpegVideoFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setRawAudioFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setWMAFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setVORBISFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setRAFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setFLACFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setMP2Format(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setAC3Format(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setAPEFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setDTSFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+ static status_t setFFmpegAudioFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+};
+
+}
+#endif
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index a981d1c..21844ca 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -39,6 +39,10 @@ public:
virtual status_t getSize(off64_t *size);
+ virtual String8 getUri() {
+ return mUri;
+ }
+
virtual sp<DecryptHandle> DrmInitialization(const char *mime);
virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
@@ -48,6 +52,7 @@ protected:
private:
int mFd;
+ String8 mUri;
int64_t mOffset;
int64_t mLength;
Mutex mLock;
@@ -60,6 +65,7 @@ private:
unsigned char *mDrmBuf;
ssize_t readAtDRM(off64_t offset, void *data, size_t size);
+ void fetchUriFromFd(int fd);
FileSource(const FileSource &);
FileSource &operator=(const FileSource &);
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 8b1e63b..ffbd20c 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -66,6 +66,41 @@ extern const char *MEDIA_MIMETYPE_TEXT_VTT;
extern const char *MEDIA_MIMETYPE_TEXT_CEA_608;
extern const char *MEDIA_MIMETYPE_DATA_TIMED_ID3;
+extern const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC;
+extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
+
+extern const char *MEDIA_MIMETYPE_VIDEO_FLV1;
+extern const char *MEDIA_MIMETYPE_VIDEO_MJPEG;
+extern const char *MEDIA_MIMETYPE_VIDEO_RV;
+extern const char *MEDIA_MIMETYPE_VIDEO_VC1;
+extern const char *MEDIA_MIMETYPE_VIDEO_WMV;
+extern const char *MEDIA_MIMETYPE_VIDEO_HEVC;
+extern const char *MEDIA_MIMETYPE_VIDEO_FFMPEG;
+
+extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
+extern const char *MEDIA_MIMETYPE_AUDIO_PCM;
+extern const char *MEDIA_MIMETYPE_AUDIO_RA;
+extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
+extern const char *MEDIA_MIMETYPE_AUDIO_FFMPEG;
+
+extern const char *MEDIA_MIMETYPE_CONTAINER_APE;
+extern const char *MEDIA_MIMETYPE_CONTAINER_DIVX;
+extern const char *MEDIA_MIMETYPE_CONTAINER_DTS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_FLAC;
+extern const char *MEDIA_MIMETYPE_CONTAINER_FLV;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MOV;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MP2;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPG;
+extern const char *MEDIA_MIMETYPE_CONTAINER_RA;
+extern const char *MEDIA_MIMETYPE_CONTAINER_RM;
+extern const char *MEDIA_MIMETYPE_CONTAINER_TS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_WEBM;
+extern const char *MEDIA_MIMETYPE_CONTAINER_VC1;
+extern const char *MEDIA_MIMETYPE_CONTAINER_HEVC;
+extern const char *MEDIA_MIMETYPE_CONTAINER_WMA;
+extern const char *MEDIA_MIMETYPE_CONTAINER_WMV;
+extern const char *MEDIA_MIMETYPE_CONTAINER_FFMPEG;
+
} // namespace android
#include <media/stagefright/ExtendedMediaDefs.h>
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 183933a..d68227c 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -19,15 +19,27 @@
#define MEDIA_EXTRACTOR_H_
#include <utils/RefBase.h>
+#include <media/stagefright/DataSource.h>
namespace android {
-class DataSource;
class MediaSource;
class MetaData;
class MediaExtractor : public RefBase {
public:
+ typedef MediaExtractor *(*CreateFunc)(const sp<DataSource> &source,
+ const char *mime, const sp<AMessage> &meta);
+
+ struct Plugin {
+ DataSource::SnifferFunc sniff;
+ CreateFunc create;
+ };
+
+ static Plugin *getPlugin() {
+ return &sPlugin;
+ }
+
static sp<MediaExtractor> Create(
const sp<DataSource> &source, const char *mime = NULL);
@@ -74,6 +86,7 @@ protected:
private:
bool mIsDrm;
+ static Plugin sPlugin;
MediaExtractor(const MediaExtractor &);
MediaExtractor &operator=(const MediaExtractor &);
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 8d4e15a..275ef55 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -50,6 +50,10 @@ enum {
kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz)
kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
kKeyBitRate = 'brte', // int32_t (bps)
+ kKeyCodecId = 'cdid', // int32_t
+ kKeyBitsPerSample = 'sbit', // int32_t (DUPE of kKeySampleBits)
+ kKeyCodedSampleBits = 'cosb', // int32_t
+ kKeySampleFormat = 'sfmt', // int32_t
kKeyESDS = 'esds', // raw data
kKeyAACProfile = 'aacp', // int32_t
kKeyAVCC = 'avcc', // raw data
@@ -131,6 +135,23 @@ enum {
kKeyIsUnreadable = 'unre', // bool (int32_t)
+ kKeyRawCodecSpecificData = 'rcsd', // raw data - added to support mmParser
+ kKeyDivXVersion = 'DivX', // int32_t
+ kKeyDivXDrm = 'QDrm', // void *
+ kKeyWMAEncodeOpt = 'eopt', // int32_t
+ kKeyWMABlockAlign = 'blka', // int32_t
+ kKeyWMAVersion = 'wmav', // int32_t
+ kKeyWMAAdvEncOpt1 = 'ade1', // int16_t
+ kKeyWMAAdvEncOpt2 = 'ade2', // int32_t
+ kKeyWMAFormatTag = 'fmtt', // int64_t
+ kKeyWMABitspersample = 'bsps', // int64_t
+ kKeyWMAVirPktSize = 'vpks', // int64_t
+ kKeyWMVProfile = 'wmvp', // int32_t
+
+ kKeyWMVVersion = 'wmvv', // int32_t
+ kKeyRVVersion = '#rvv', // int32_t
+ kKeyBlockAlign = 'blk', // int32_t , should be different from kKeyWMABlockAlign
+
// An indication that a video buffer has been rendered.
kKeyRendered = 'rend', // bool (int32_t)
@@ -181,6 +202,9 @@ enum {
// H264 supplemental enhancement information offsets/sizes
kKeySEI = 'sei ', // raw data
+
+ kKeyPCMFormat = 'pfmt',
+ kKeyArbitraryMode = 'ArbM',
};
enum {
@@ -190,6 +214,32 @@ enum {
kTypeD263 = 'd263',
};
+enum {
+ kTypeDivXVer_3_11,
+ kTypeDivXVer_4,
+ kTypeDivXVer_5,
+ kTypeDivXVer_6,
+};
+
+enum {
+ kTypeWMA,
+ kTypeWMAPro,
+ kTypeWMALossLess,
+};
+
+enum {
+ kTypeWMVVer_7, // WMV1
+ kTypeWMVVer_8, // WMV2
+ kTypeWMVVer_9, // WMV3
+};
+
+// http://en.wikipedia.org/wiki/RealVideo
+enum {
+ kTypeRVVer_G2, // rv20: RealVideo G2
+ kTypeRVVer_8, // rv30: RealVideo 8
+ kTypeRVVer_9, // rv40: RealVideo 9
+};
+
class MetaData : public RefBase {
public:
MetaData();
diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
index aacf76a..20149b3 100644
--- a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
+++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
@@ -33,6 +33,8 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaDefs.h>
+
#include <nuplayer/NuPlayer.h>
#include <nuplayer/NuPlayerDecoderBase.h>
#include <nuplayer/NuPlayerDecoderPassThrough.h>
@@ -52,12 +54,29 @@ bool AVNuUtils::pcmOffloadException(const sp<MetaData> &) {
return true;
}
-bool AVNuUtils::isRAWFormat(const sp<MetaData> &) {
- return false;
+bool AVNuUtils::isRAWFormat(const sp<MetaData> &meta) {
+ const char *mime = {0};
+ if (meta == NULL) {
+ return false;
+ }
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ if (!strncasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW, 9))
+ return true;
+ else
+ return false;
}
-bool AVNuUtils::isRAWFormat(const sp<AMessage> &) {
- return false;
+bool AVNuUtils::isRAWFormat(const sp<AMessage> &format) {
+ AString mime;
+ if (format == NULL) {
+ return false;
+ }
+ CHECK(format->findString("mime", &mime));
+ if (!strncasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW, 9))
+ return true;
+ else
+ return false;
+
}
bool AVNuUtils::isVorbisFormat(const sp<MetaData> &) {
@@ -69,20 +88,39 @@ int AVNuUtils::updateAudioBitWidth(audio_format_t /*audioFormat*/,
return 16;
}
-audio_format_t AVNuUtils::getKeyPCMFormat(const sp<MetaData> &) {
- return AUDIO_FORMAT_INVALID;
-}
+audio_format_t AVNuUtils::getKeyPCMFormat(const sp<MetaData> &meta) {
+ int32_t pcmFormat = 0;
+ if (meta->findInt32('pfmt', &pcmFormat))
+ return (audio_format_t)pcmFormat;
-void AVNuUtils::setKeyPCMFormat(const sp<MetaData> &, audio_format_t /*audioFormat*/) {
+ return AUDIO_FORMAT_PCM_16_BIT;
+}
+void AVNuUtils::setKeyPCMFormat(const sp<MetaData> &meta, audio_format_t audioFormat) {
+ if (audio_is_linear_pcm(audioFormat))
+ meta->setInt32('pfmt', audioFormat);
}
-audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &) {
+audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &format) {
+ int32_t pcmFormat = 0;
+ if (format->findInt32("pcm-format", &pcmFormat))
+ return (audio_format_t)pcmFormat;
+
+ int32_t bits = 16;
+ if (format->findInt32("bit-width", &bits)) {
+ if (bits == 8)
+ return AUDIO_FORMAT_PCM_8_BIT;
+ if (bits == 24)
+ return AUDIO_FORMAT_PCM_32_BIT;
+ if (bits == 32)
+ return AUDIO_FORMAT_PCM_FLOAT;
+ }
return AUDIO_FORMAT_PCM_16_BIT;
}
-void AVNuUtils::setPCMFormat(const sp<AMessage> &, audio_format_t /*audioFormat*/) {
-
+void AVNuUtils::setPCMFormat(const sp<AMessage> &format, audio_format_t audioFormat) {
+ if (audio_is_linear_pcm(audioFormat))
+ format->setInt32("pcm-format", audioFormat);
}
void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &) {
diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp
index 324ff9b..50c0f89 100644
--- a/media/libavextensions/stagefright/AVUtils.cpp
+++ b/media/libavextensions/stagefright/AVUtils.cpp
@@ -66,8 +66,10 @@ int AVUtils::getAudioSampleBits(const sp<MetaData> &) {
return 16;
}
-int AVUtils::getAudioSampleBits(const sp<AMessage> &) {
- return 16;
+int AVUtils::getAudioSampleBits(const sp<AMessage> &format) {
+ int32_t bits = 16;
+ format->findInt32("bit-width", &bits);
+ return bits;
}
void AVUtils::setPcmSampleBits(const sp<AMessage> &, int32_t /*bitWidth*/) {
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 005cb4b..6729cd5 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -24,7 +24,8 @@ LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright/timedtext \
$(TOP)/frameworks/av/media/libmediaplayerservice \
$(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/frameworks/av/media/libavextensions \
+ $(TOP)/frameworks/av/media/libavextensions \
+ $(TOP)/frameworks/av/include/media \
LOCAL_CFLAGS += -Werror -Wall
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index f83eaf6..2b164ac 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -35,6 +35,7 @@
#include <media/stagefright/MediaErrors.h>
#include <stagefright/AVExtensions.h>
+#include <stagefright/FFMPEGSoftCodec.h>
#include <gui/Surface.h>
#include "avc_utils.h"
@@ -257,9 +258,16 @@ void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
mCodec = AVUtils::get()->createCustomComponentByName(mCodecLooper, mime.c_str(), false /* encoder */, format);
+ FFMPEGSoftCodec::overrideComponentName(0, format, &mComponentName, &mime, false);
+
if (mCodec == NULL) {
- mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
+ if (!mComponentName.startsWith(mime.c_str())) {
+ mCodec = MediaCodec::CreateByComponentName(mCodecLooper, mComponentName.c_str());
+ } else {
+ mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
+ }
}
+
int32_t secure = 0;
if (format->findInt32("secure", &secure) && secure != 0) {
if (mCodec != NULL) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 9d2f134..b034459 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -26,6 +26,7 @@
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/AWakeLock.h>
#include <media/stagefright/MediaClock.h>
+#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
@@ -1678,13 +1679,17 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
}
+ int32_t bitWidth = 16;
+ format->findInt32("bit-width", &bitWidth);
+
int32_t sampleRate;
CHECK(format->findInt32("sample-rate", &sampleRate));
+ AString mime;
+ CHECK(format->findString("mime", &mime));
+
if (offloadingAudio()) {
audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
- AString mime;
- CHECK(format->findString("mime", &mime));
status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
if (err != OK) {
@@ -1692,15 +1697,11 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
"audio_format", mime.c_str());
onDisableOffloadAudio();
} else {
- int32_t bitWidth = 16;
- ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
- mime.c_str(), audioFormat);
-
audioFormat = AVUtils::get()->updateAudioFormat(audioFormat, format);
bitWidth = AVUtils::get()->getAudioSampleBits(format);
int avgBitRate = -1;
- format->findInt32("bit-rate", &avgBitRate);
+ format->findInt32("bitrate", &avgBitRate);
int32_t aacProfile = -1;
if (audioFormat == AUDIO_FORMAT_AAC
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 18d221b..a01c63a 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -44,6 +44,8 @@
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/SurfaceUtils.h>
+#include <media/stagefright/FFMPEGSoftCodec.h>
+
#include <media/hardware/HardwareAPI.h>
#include <OMX_AudioExt.h>
@@ -541,7 +543,12 @@ ACodec::ACodec()
ACodec::~ACodec() {
}
-status_t ACodec::setupCustomCodec(status_t err, const char *, const sp<AMessage> &) {
+status_t ACodec::setupCustomCodec(status_t err, const char *mime, const sp<AMessage> &msg) {
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11) && !mIsEncoder) {
+ return FFMPEGSoftCodec::setAudioFormat(
+ msg, mime, mOMX, mNode);
+ }
+
return err;
}
@@ -1589,7 +1596,11 @@ status_t ACodec::setComponentRole(
}
if (i == kNumMimeToRole) {
- return ERROR_UNSUPPORTED;
+ status_t err = ERROR_UNSUPPORTED;
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::setSupportedRole(mOMX, mNode, isEncoder, mime);
+ }
+ return err;
}
const char *role =
@@ -1910,7 +1921,8 @@ status_t ACodec::configureCodec(
if (video) {
// determine need for software renderer
bool usingSwRenderer = false;
- if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
+ if (haveNativeWindow && (mComponentName.startsWith("OMX.google.") ||
+ mComponentName.startsWith("OMX.ffmpeg."))) {
usingSwRenderer = true;
haveNativeWindow = false;
}
@@ -1995,10 +2007,12 @@ status_t ACodec::configureCodec(
// and have the decoder figure it all out.
err = OK;
} else {
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bit-width", &bitsPerSample);
err = setupRawAudioFormat(
encoder ? kPortIndexInput : kPortIndexOutput,
sampleRate,
- numChannels);
+ numChannels, bitsPerSample);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
int32_t numChannels, sampleRate;
@@ -2073,11 +2087,7 @@ status_t ACodec::configureCodec(
}
err = setupG711Codec(encoder, sampleRate, numChannels);
}
-#ifdef QTI_FLAC_DECODER
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) && encoder) {
-#else
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
-#endif
int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
if (encoder &&
(!msg->findInt32("channel-count", &numChannels)
@@ -2113,16 +2123,21 @@ status_t ACodec::configureCodec(
|| !msg->findInt32("sample-rate", &sampleRate)) {
err = INVALID_OPERATION;
} else {
- err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bit-width", &bitsPerSample);
+ err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, bitsPerSample);
}
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
+ } else if (!strncmp(mComponentName.c_str(), "OMX.google.", 11)
+ && !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
int32_t numChannels;
int32_t sampleRate;
if (!msg->findInt32("channel-count", &numChannels)
|| !msg->findInt32("sample-rate", &sampleRate)) {
err = INVALID_OPERATION;
} else {
- err = setupAC3Codec(encoder, numChannels, sampleRate);
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bit-width", &bitsPerSample);
+ err = setupAC3Codec(encoder, numChannels, sampleRate, bitsPerSample);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
int32_t numChannels;
@@ -2131,7 +2146,9 @@ status_t ACodec::configureCodec(
|| !msg->findInt32("sample-rate", &sampleRate)) {
err = INVALID_OPERATION;
} else {
- err = setupEAC3Codec(encoder, numChannels, sampleRate);
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bit-width", &bitsPerSample);
+ err = setupEAC3Codec(encoder, numChannels, sampleRate, bitsPerSample);
}
} else {
err = setupCustomCodec(err, mime, msg);
@@ -2448,9 +2465,9 @@ status_t ACodec::setupAACCodec(
}
status_t ACodec::setupAC3Codec(
- bool encoder, int32_t numChannels, int32_t sampleRate) {
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t bitsPerSample) {
status_t err = setupRawAudioFormat(
- encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+ encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels, bitsPerSample);
if (err != OK) {
return err;
@@ -2486,9 +2503,9 @@ status_t ACodec::setupAC3Codec(
}
status_t ACodec::setupEAC3Codec(
- bool encoder, int32_t numChannels, int32_t sampleRate) {
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t bitsPerSample) {
status_t err = setupRawAudioFormat(
- encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+ encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels, bitsPerSample);
if (err != OK) {
return err;
@@ -2634,7 +2651,7 @@ status_t ACodec::setupFlacCodec(
}
status_t ACodec::setupRawAudioFormat(
- OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, int32_t bitsPerSample) {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = portIndex;
@@ -2669,7 +2686,7 @@ status_t ACodec::setupRawAudioFormat(
pcmParams.nChannels = numChannels;
pcmParams.eNumData = OMX_NumericalDataSigned;
pcmParams.bInterleaved = OMX_TRUE;
- pcmParams.nBitPerSample = 16;
+ pcmParams.nBitPerSample = bitsPerSample;
pcmParams.nSamplingRate = sampleRate;
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
@@ -2896,7 +2913,13 @@ status_t ACodec::setupVideoDecoder(
status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
if (err != OK) {
- return err;
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::setVideoFormat(
+ msg, mime, mOMX, mNode, mIsEncoder, &compressionFormat);
+ }
+ if (err != OK) {
+ return err;
+ }
}
err = setVideoPortFormatType(
@@ -3046,7 +3069,14 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
if (err != OK) {
- return err;
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::setVideoFormat(
+ msg, mime, mOMX, mNode, mIsEncoder, &compressionFormat);
+ }
+ if (err != OK) {
+ ALOGE("Not a supported video mime type: %s", mime);
+ return err;
+ }
}
err = setVideoPortFormatType(
@@ -4154,6 +4184,14 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
default:
{
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::getVideoPortFormat(portIndex,
+ (int)videoDef->eCompressionFormat, notify, mOMX, mNode);
+ }
+ if (err == OK) {
+ break;
+ }
+
if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
// should be CodingUnused
ALOGE("Raw port video compression format is %s(%d)",
@@ -4200,7 +4238,9 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
if (params.nChannels <= 0
|| (params.nChannels != 1 && !params.bInterleaved)
|| (params.nBitPerSample != 16u
- && params.nBitPerSample != 24u)// we support 16/24 bit s/w decoding
+ && params.nBitPerSample != 24u
+ && params.nBitPerSample != 32u
+ && params.nBitPerSample != 8u)// we support 8/16/24/32 bit s/w decoding
|| params.eNumData != OMX_NumericalDataSigned
|| params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
@@ -4216,6 +4256,7 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
notify->setInt32("channel-count", params.nChannels);
notify->setInt32("sample-rate", params.nSamplingRate);
notify->setInt32("bit-width", params.nBitPerSample);
+
if (mChannelMaskPresent) {
notify->setInt32("channel-mask", mChannelMask);
}
@@ -4265,6 +4306,7 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
case OMX_AUDIO_CodingFLAC:
{
+ if (portIndex == kPortIndexInput) {
OMX_AUDIO_PARAM_FLACTYPE params;
InitOMXParams(&params);
params.nPortIndex = portIndex;
@@ -4279,6 +4321,7 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
notify->setInt32("channel-count", params.nChannels);
notify->setInt32("sample-rate", params.nSampleRate);
break;
+ }
}
case OMX_AUDIO_CodingMP3:
@@ -4419,6 +4462,14 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
}
default:
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::getAudioPortFormat(portIndex,
+ (int)audioDef->eEncoding, notify, mOMX, mNode);
+ }
+ if (err == OK) {
+ break;
+ }
+
ALOGE("Unsupported audio coding: %s(%d)\n",
asString(audioDef->eEncoding), audioDef->eEncoding);
return BAD_TYPE;
@@ -5718,8 +5769,79 @@ bool ACodec::LoadedState::onConfigureComponent(
ALOGE("[%s] configureCodec returning error %d",
mCodec->mComponentName.c_str(), err);
- mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
- return false;
+ int32_t encoder;
+ if (!msg->findInt32("encoder", &encoder)) {
+ encoder = false;
+ }
+
+ if (!encoder && !strncmp(mime.c_str(), "video/", strlen("video/"))) {
+ Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
+
+ OMXCodec::findMatchingCodecs(
+ mime.c_str(),
+ encoder, // createEncoder
+ NULL, // matchComponentName
+ 0, // flags
+ &matchingCodecs);
+
+ status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
+
+ if (err != OK) {
+ ALOGE("Failed to freeNode");
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ return false;
+ }
+
+ mCodec->mNode = 0;
+ AString componentName;
+ sp<CodecObserver> observer = new CodecObserver;
+
+ err = NAME_NOT_FOUND;
+ for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+ ++matchIndex) {
+ componentName = matchingCodecs.itemAt(matchIndex).mName.string();
+ if (!strcmp(mCodec->mComponentName.c_str(), componentName.c_str())) {
+ continue;
+ }
+
+ pid_t tid = gettid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+ err = mCodec->mOMX->allocateNode(componentName.c_str(), observer, &mCodec->mNode);
+ androidSetThreadPriority(tid, prevPriority);
+
+ if (err == OK) {
+ break;
+ } else {
+ ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
+ }
+
+ mCodec->mNode = 0;
+ }
+
+ if (mCodec->mNode == 0) {
+ if (!mime.empty()) {
+ ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
+ encoder ? "en" : "de", mime.c_str(), err);
+ } else {
+ ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
+ }
+
+ mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
+ return false;
+ }
+
+ sp<AMessage> notify = new AMessage(kWhatOMXMessageList, mCodec);
+ observer->setNotificationMessage(notify);
+ mCodec->mComponentName = componentName;
+
+ err = mCodec->configureCodec(mime.c_str(), msg);
+
+ if (err != OK) {
+ mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
+ return false;
+ }
+ }
}
{
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 36b1cf4..09ff302 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -70,6 +70,7 @@ LOCAL_SRC_FILES:= \
XINGSeeker.cpp \
avc_utils.cpp \
APE.cpp \
+ FFMPEGSoftCodec.cpp \
LOCAL_C_INCLUDES:= \
$(TOP)/frameworks/av/include/media/ \
@@ -140,6 +141,9 @@ endif
LOCAL_CLANG := true
+# FFMPEG plugin
+LOCAL_C_INCLUDES += $(TOP)/external/stagefright-plugins/include
+
LOCAL_MODULE:= libstagefright
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 9230329..39326c9 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -47,11 +47,28 @@
#include <utils/String8.h>
#include <cutils/properties.h>
+#include <cutils/log.h>
+
+#include <dlfcn.h>
#include <stagefright/AVExtensions.h>
namespace android {
+static void *loadExtractorPlugin() {
+ void *ret = NULL;
+ char lib[PROPERTY_VALUE_MAX];
+ if (property_get("media.sf.extractor-plugin", lib, NULL)) {
+ if (void *extractorLib = ::dlopen(lib, RTLD_LAZY)) {
+ ret = ::dlsym(extractorLib, "getExtractorPlugin");
+ ALOGW_IF(!ret, "Failed to find symbol, dlerror: %s", ::dlerror());
+ } else {
+ ALOGV("Failed to load %s, dlerror: %s", lib, ::dlerror());
+ }
+ }
+ return ret;
+}
+
bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
*x = 0;
@@ -119,7 +136,7 @@ bool DataSource::sniff(
}
// static
-void DataSource::RegisterSniffer_l(SnifferFunc func) {
+void DataSource::RegisterSniffer_l(SnifferFunc /* func */) {
return;
}
@@ -137,6 +154,13 @@ Sniffer::Sniffer() {
bool Sniffer::sniff(
DataSource *source, String8 *mimeType, float *confidence, sp<AMessage> *meta) {
+ bool forceExtraSniffers = false;
+
+ if (*confidence == 3.14f) {
+ // Magic value, as set by MediaExtractor when a video container looks incomplete
+ forceExtraSniffers = true;
+ }
+
*mimeType = "";
*confidence = 0.0f;
meta->clear();
@@ -156,6 +180,23 @@ bool Sniffer::sniff(
}
}
+ /* Only do the deeper sniffers if the results are null or in doubt */
+ if (mimeType->length() == 0 || *confidence < 0.21f || forceExtraSniffers) {
+ for (List<SnifferFunc>::iterator it = mExtraSniffers.begin();
+ it != mExtraSniffers.end(); ++it) {
+ String8 newMimeType;
+ float newConfidence;
+ sp<AMessage> newMeta;
+ if ((*it)(source, &newMimeType, &newConfidence, &newMeta)) {
+ if (newConfidence > *confidence) {
+ *mimeType = newMimeType;
+ *confidence = newConfidence;
+ *meta = newMeta;
+ }
+ }
+ }
+ }
+
return *confidence > 0.0;
}
@@ -171,6 +212,26 @@ void Sniffer::registerSniffer_l(SnifferFunc func) {
mSniffers.push_back(func);
}
+void Sniffer::registerSnifferPlugin() {
+ static void (*getExtractorPlugin)(MediaExtractor::Plugin *) =
+ (void (*)(MediaExtractor::Plugin *))loadExtractorPlugin();
+
+ MediaExtractor::Plugin *plugin = MediaExtractor::getPlugin();
+ if (!plugin->sniff && getExtractorPlugin) {
+ getExtractorPlugin(plugin);
+ }
+ if (plugin->sniff) {
+ for (List<SnifferFunc>::iterator it = mExtraSniffers.begin();
+ it != mExtraSniffers.end(); ++it) {
+ if (*it == plugin->sniff) {
+ return;
+ }
+ }
+
+ mExtraSniffers.push_back(plugin->sniff);
+ }
+}
+
void Sniffer::registerDefaultSniffers() {
Mutex::Autolock autoLock(mSnifferMutex);
@@ -185,8 +246,9 @@ void Sniffer::registerDefaultSniffers() {
registerSniffer_l(SniffAAC);
registerSniffer_l(SniffMPEG2PS);
registerSniffer_l(SniffWVM);
- RegisterSniffer_l(SniffMidi);
- RegisterSniffer_l(AVUtils::get()->getExtendedSniffer());
+ registerSniffer_l(SniffMidi);
+ registerSniffer_l(AVUtils::get()->getExtendedSniffer());
+ registerSnifferPlugin();
char value[PROPERTY_VALUE_MAX];
if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/FFMPEGSoftCodec.cpp b/media/libstagefright/FFMPEGSoftCodec.cpp
new file mode 100644
index 0000000..3e6692b
--- /dev/null
+++ b/media/libstagefright/FFMPEGSoftCodec.cpp
@@ -0,0 +1,1149 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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 "FFMPEGSoftCodec"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ABitReader.h>
+
+#include <media/stagefright/FFMPEGSoftCodec.h>
+
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/Utils.h>
+
+#include <OMX_Component.h>
+#include <OMX_AudioExt.h>
+#include <OMX_IndexExt.h>
+
+#include <OMX_FFMPEG_Extn.h>
+
+namespace android {
+
+enum MetaKeyType{
+ INT32, INT64, STRING, DATA, CSD
+};
+
+struct MetaKeyEntry{
+ int MetaKey;
+ const char* MsgKey;
+ MetaKeyType KeyType;
+};
+
+static const MetaKeyEntry MetaKeyTable[] {
+ {kKeyAACAOT , "aac-profile" , INT32},
+ {kKeyArbitraryMode , "use-arbitrary-mode" , INT32},
+ {kKeyBitRate , "bitrate" , INT32},
+ {kKeyBitsPerSample , "bit-width" , INT32},
+ {kKeyBlockAlign , "block-align" , INT32},
+ {kKeyChannelCount , "channel-count" , INT32},
+ {kKeyCodecId , "codec-id" , INT32},
+ {kKeyCodedSampleBits , "coded-sample-bits" , INT32},
+ {kKeyRawCodecSpecificData , "raw-codec-specific-data", CSD},
+ {kKeyRVVersion , "rv-version" , INT32},
+ {kKeySampleFormat , "sample-format" , INT32},
+ {kKeySampleRate , "sample-rate" , INT32},
+ {kKeyWMAVersion , "wma-version" , INT32}, // int32_t
+ {kKeyWMVVersion , "wmv-version" , INT32},
+ {kKeyPCMFormat , "pcm-format" , INT32},
+};
+
+const char* FFMPEGSoftCodec::getMsgKey(int key) {
+ static const size_t numMetaKeys =
+ sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]);
+ size_t i;
+ for (i = 0; i < numMetaKeys; ++i) {
+ if (key == MetaKeyTable[i].MetaKey) {
+ return MetaKeyTable[i].MsgKey;
+ }
+ }
+ return "unknown";
+}
+
+void FFMPEGSoftCodec::convertMetaDataToMessageFF(
+ const sp<MetaData> &meta, sp<AMessage> *format) {
+ const char * str_val;
+ int32_t int32_val;
+ int64_t int64_val;
+ uint32_t data_type;
+ const void * data;
+ size_t size;
+ static const size_t numMetaKeys =
+ sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]);
+ size_t i;
+ for (i = 0; i < numMetaKeys; ++i) {
+ if (MetaKeyTable[i].KeyType == INT32 &&
+ meta->findInt32(MetaKeyTable[i].MetaKey, &int32_val)) {
+ ALOGV("found metakey %s of type int32", MetaKeyTable[i].MsgKey);
+ format->get()->setInt32(MetaKeyTable[i].MsgKey, int32_val);
+ } else if (MetaKeyTable[i].KeyType == INT64 &&
+ meta->findInt64(MetaKeyTable[i].MetaKey, &int64_val)) {
+ ALOGV("found metakey %s of type int64", MetaKeyTable[i].MsgKey);
+ format->get()->setInt64(MetaKeyTable[i].MsgKey, int64_val);
+ } else if (MetaKeyTable[i].KeyType == STRING &&
+ meta->findCString(MetaKeyTable[i].MetaKey, &str_val)) {
+ ALOGV("found metakey %s of type string", MetaKeyTable[i].MsgKey);
+ format->get()->setString(MetaKeyTable[i].MsgKey, str_val);
+ } else if ( (MetaKeyTable[i].KeyType == DATA ||
+ MetaKeyTable[i].KeyType == CSD) &&
+ meta->findData(MetaKeyTable[i].MetaKey, &data_type, &data, &size)) {
+ ALOGV("found metakey %s of type data", MetaKeyTable[i].MsgKey);
+ if (MetaKeyTable[i].KeyType == CSD) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ format->get()->setBuffer("csd-0", buffer);
+ } else {
+ const uint8_t *ptr = (const uint8_t *)data;
+ CHECK(size >= 8);
+ int seqLength = 0, picLength = 0;
+ for (size_t i = 4; i < (size - 4); i++)
+ {
+ if ((*(ptr + i) == 0) && (*(ptr + i + 1) == 0) &&
+ (*(ptr + i + 2) == 0) && (*(ptr + i + 3) == 1))
+ seqLength = i;
+ }
+ sp<ABuffer> buffer = new ABuffer(seqLength);
+ memcpy(buffer->data(), data, seqLength);
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ format->get()->setBuffer("csd-0", buffer);
+ picLength=size-seqLength;
+ sp<ABuffer> buffer1 = new ABuffer(picLength);
+ memcpy(buffer1->data(), (const uint8_t *)data + seqLength, picLength);
+ buffer1->meta()->setInt32("csd", true);
+ buffer1->meta()->setInt64("timeUs", 0);
+ format->get()->setBuffer("csd-1", buffer1);
+ }
+ } else {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+ format->get()->setBuffer(MetaKeyTable[i].MsgKey, buffer);
+ }
+ }
+
+ }
+}
+
+void FFMPEGSoftCodec::convertMessageToMetaDataFF(
+ const sp<AMessage> &msg, sp<MetaData> &meta) {
+ AString str_val;
+ int32_t int32_val;
+ int64_t int64_val;
+ static const size_t numMetaKeys =
+ sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]);
+ size_t i;
+ for (i = 0; i < numMetaKeys; ++i) {
+ if (MetaKeyTable[i].KeyType == INT32 &&
+ msg->findInt32(MetaKeyTable[i].MsgKey, &int32_val)) {
+ ALOGV("found metakey %s of type int32", MetaKeyTable[i].MsgKey);
+ meta->setInt32(MetaKeyTable[i].MetaKey, int32_val);
+ } else if (MetaKeyTable[i].KeyType == INT64 &&
+ msg->findInt64(MetaKeyTable[i].MsgKey, &int64_val)) {
+ ALOGV("found metakey %s of type int64", MetaKeyTable[i].MsgKey);
+ meta->setInt64(MetaKeyTable[i].MetaKey, int64_val);
+ } else if (MetaKeyTable[i].KeyType == STRING &&
+ msg->findString(MetaKeyTable[i].MsgKey, &str_val)) {
+ ALOGV("found metakey %s of type string", MetaKeyTable[i].MsgKey);
+ meta->setCString(MetaKeyTable[i].MetaKey, str_val.c_str());
+ }
+ }
+}
+
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+void FFMPEGSoftCodec::overrideComponentName(
+ uint32_t /*quirks*/, const sp<AMessage> &msg, AString* componentName, AString* mime, int32_t isEncoder) {
+
+ int32_t wmvVersion = 0;
+ if (!strncasecmp(mime->c_str(), MEDIA_MIMETYPE_VIDEO_WMV, strlen(MEDIA_MIMETYPE_VIDEO_WMV)) &&
+ msg->findInt32(getMsgKey(kKeyWMVVersion), &wmvVersion)) {
+ ALOGD("Found WMV version key %d", wmvVersion);
+ if (wmvVersion == 1) {
+ ALOGD("Use FFMPEG for unsupported WMV track");
+ componentName->setTo("OMX.ffmpeg.wmv.decoder");
+ }
+ }
+
+ int32_t encodeOptions = 0;
+ if (!isEncoder && !strncasecmp(mime->c_str(), MEDIA_MIMETYPE_AUDIO_WMA, strlen(MEDIA_MIMETYPE_AUDIO_WMA)) &&
+ !msg->findInt32(getMsgKey(kKeyWMAEncodeOpt), &encodeOptions)) {
+ ALOGD("Use FFMPEG for unsupported WMA track");
+ componentName->setTo("OMX.ffmpeg.wma.decoder");
+ }
+
+ // Google's decoder doesn't support MAIN profile
+ int32_t aacProfile = 0;
+ if (!isEncoder && !strncasecmp(mime->c_str(), MEDIA_MIMETYPE_AUDIO_AAC, strlen(MEDIA_MIMETYPE_AUDIO_AAC)) &&
+ msg->findInt32(getMsgKey(kKeyAACAOT), &aacProfile)) {
+ if (aacProfile == OMX_AUDIO_AACObjectMain) {
+ ALOGD("Use FFMPEG for AAC MAIN profile");
+ componentName->setTo("OMX.ffmpeg.aac.decoder");
+ }
+ }
+}
+
+status_t FFMPEGSoftCodec::setVideoFormat(
+ const sp<AMessage> &msg, const char* mime, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID, bool isEncoder,
+ OMX_VIDEO_CODINGTYPE *compressionFormat) {
+ status_t err = OK;
+
+ if (isEncoder) {
+ ALOGE("Encoding not supported");
+ err = BAD_VALUE;
+
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_WMV, mime)) {
+ err = setWMVFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setWMVFormat() failed (err = %d)", err);
+ } else {
+ *compressionFormat = OMX_VIDEO_CodingWMV;
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_RV, mime)) {
+ err = setRVFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setRVFormat() failed (err = %d)", err);
+ } else {
+ *compressionFormat = OMX_VIDEO_CodingRV;
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VC1, mime)) {
+ *compressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingVC1;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_FLV1, mime)) {
+ *compressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingFLV1;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX, mime)) {
+ *compressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingDIVX;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
+ *compressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingHEVC;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_FFMPEG, mime)) {
+ ALOGV("Setting the OMX_VIDEO_PARAM_FFMPEGTYPE params");
+ err = setFFmpegVideoFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setFFmpegVideoFormat() failed (err = %d)", err);
+ } else {
+ *compressionFormat = OMX_VIDEO_CodingAutoDetect;
+ }
+ } else {
+ err = BAD_TYPE;
+ }
+
+ return err;
+}
+
+status_t FFMPEGSoftCodec::getVideoPortFormat(OMX_U32 portIndex, int coding,
+ sp<AMessage> &notify, sp<IOMX> OMXHandle, IOMX::node_id nodeId) {
+
+ status_t err = BAD_TYPE;
+ switch (coding) {
+ case OMX_VIDEO_CodingWMV:
+ {
+ OMX_VIDEO_PARAM_WMVTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, OMX_IndexParamVideoWmv, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ int32_t version;
+ if (params.eFormat == OMX_VIDEO_WMVFormat7) {
+ version = kTypeWMVVer_7;
+ } else if (params.eFormat == OMX_VIDEO_WMVFormat8) {
+ version = kTypeWMVVer_8;
+ } else {
+ version = kTypeWMVVer_9;
+ }
+ notify->setString("mime", MEDIA_MIMETYPE_VIDEO_WMV);
+ notify->setInt32("wmv-version", version);
+ break;
+ }
+ case OMX_VIDEO_CodingAutoDetect:
+ {
+ OMX_VIDEO_PARAM_FFMPEGTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamVideoFFmpeg, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_VIDEO_FFMPEG);
+ notify->setInt32("codec-id", params.eCodecId);
+ break;
+ }
+ case OMX_VIDEO_CodingRV:
+ {
+ OMX_VIDEO_PARAM_RVTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamVideoRv, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ int32_t version;
+ if (params.eFormat == OMX_VIDEO_RVFormatG2) {
+ version = kTypeRVVer_G2;
+ } else if (params.eFormat == OMX_VIDEO_RVFormat8) {
+ version = kTypeRVVer_8;
+ } else {
+ version = kTypeRVVer_9;
+ }
+ notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RV);
+ break;
+ }
+ }
+ return err;
+}
+
+status_t FFMPEGSoftCodec::getAudioPortFormat(OMX_U32 portIndex, int coding,
+ sp<AMessage> &notify, sp<IOMX> OMXHandle, IOMX::node_id nodeId) {
+
+ status_t err = BAD_TYPE;
+ switch (coding) {
+ case OMX_AUDIO_CodingRA:
+ {
+ OMX_AUDIO_PARAM_RATYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, OMX_IndexParamAudioRa, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RA);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSamplingRate);
+ break;
+ }
+ case OMX_AUDIO_CodingMP2:
+ {
+ OMX_AUDIO_PARAM_MP2TYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamAudioMp2, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSampleRate);
+ break;
+ }
+ case OMX_AUDIO_CodingWMA:
+ {
+ OMX_AUDIO_PARAM_WMATYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, OMX_IndexParamAudioWma, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_WMA);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSamplingRate);
+ break;
+ }
+ case OMX_AUDIO_CodingAPE:
+ {
+ OMX_AUDIO_PARAM_APETYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamAudioApe, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_APE);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSamplingRate);
+ notify->setInt32("bit-width", params.nBitsPerSample);
+ break;
+ }
+ case OMX_AUDIO_CodingFLAC:
+ {
+ OMX_AUDIO_PARAM_FLACTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamAudioFlac, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSampleRate);
+ notify->setInt32("bit-width", params.nCompressionLevel); // piggyback
+ break;
+ }
+
+ case OMX_AUDIO_CodingDTS:
+ {
+ OMX_AUDIO_PARAM_DTSTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamAudioDts, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_DTS);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSamplingRate);
+ break;
+ }
+ case OMX_AUDIO_CodingAC3:
+ {
+ OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSampleRate);
+ break;
+ }
+
+ case OMX_AUDIO_CodingAutoDetect:
+ {
+ OMX_AUDIO_PARAM_FFMPEGTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = OMXHandle->getParameter(
+ nodeId, (OMX_INDEXTYPE)OMX_IndexParamAudioFFmpeg, &params, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FFMPEG);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSampleRate);
+ break;
+ }
+ }
+ return err;
+}
+
+status_t FFMPEGSoftCodec::setAudioFormat(
+ const sp<AMessage> &msg, const char* mime, sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID) {
+ ALOGV("setAudioFormat called");
+ status_t err = OK;
+
+ ALOGV("setAudioFormat: %s", msg->debugString(0).c_str());
+
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_WMA, mime)) {
+ err = setWMAFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setWMAFormat() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_VORBIS, mime)) {
+ err = setVORBISFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setVORBISFormat() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RA, mime)) {
+ err = setRAFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setRAFormat() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_FLAC, mime)) {
+ err = setFLACFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setFLACFormat() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, mime)) {
+ err = setMP2Format(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setMP2Format() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mime)) {
+ err = setAC3Format(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setAC3Format() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_APE, mime)) {
+ err = setAPEFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setAPEFormat() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_DTS, mime)) {
+ err = setDTSFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setDTSFormat() failed (err = %d)", err);
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_FFMPEG, mime)) {
+ err = setFFmpegAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK) {
+ ALOGE("setFFmpegAudioFormat() failed (err = %d)", err);
+ }
+ }
+
+ return err;
+}
+
+status_t FFMPEGSoftCodec::setSupportedRole(
+ const sp<IOMX> &omx, IOMX::node_id node,
+ bool isEncoder, const char *mime) {
+
+ ALOGV("setSupportedRole Called %s", mime);
+
+ struct MimeToRole {
+ const char *mime;
+ const char *decoderRole;
+ const char *encoderRole;
+ };
+
+ static const MimeToRole kFFMPEGMimeToRole[] = {
+ { MEDIA_MIMETYPE_AUDIO_AAC,
+ "audio_decoder.aac", NULL },
+ { MEDIA_MIMETYPE_AUDIO_MPEG,
+ "audio_decoder.mp3", NULL },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS,
+ "audio_decoder.vorbis", NULL },
+ { MEDIA_MIMETYPE_AUDIO_WMA,
+ "audio_decoder.wma", NULL },
+ { MEDIA_MIMETYPE_AUDIO_RA,
+ "audio_decoder.ra" , NULL },
+ { MEDIA_MIMETYPE_AUDIO_FLAC,
+ "audio_decoder.flac", NULL },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ "audio_decoder.mp2", NULL },
+ { MEDIA_MIMETYPE_AUDIO_AC3,
+ "audio_decoder.ac3", NULL },
+ { MEDIA_MIMETYPE_AUDIO_APE,
+ "audio_decoder.ape", NULL },
+ { MEDIA_MIMETYPE_AUDIO_DTS,
+ "audio_decoder.dts", NULL },
+ { MEDIA_MIMETYPE_VIDEO_MPEG2,
+ "video_decoder.mpeg2", NULL },
+ { MEDIA_MIMETYPE_VIDEO_DIVX,
+ "video_decoder.divx", NULL },
+ { MEDIA_MIMETYPE_VIDEO_DIVX4,
+ "video_decoder.divx", NULL },
+ { MEDIA_MIMETYPE_VIDEO_DIVX311,
+ "video_decoder.divx", NULL },
+ { MEDIA_MIMETYPE_VIDEO_WMV,
+ "video_decoder.wmv", NULL },
+ { MEDIA_MIMETYPE_VIDEO_VC1,
+ "video_decoder.vc1", NULL },
+ { MEDIA_MIMETYPE_VIDEO_RV,
+ "video_decoder.rv", NULL },
+ { MEDIA_MIMETYPE_VIDEO_FLV1,
+ "video_decoder.flv1", NULL },
+ { MEDIA_MIMETYPE_VIDEO_HEVC,
+ "video_decoder.hevc", NULL },
+ { MEDIA_MIMETYPE_AUDIO_FFMPEG,
+ "audio_decoder.trial", NULL },
+ { MEDIA_MIMETYPE_VIDEO_FFMPEG,
+ "video_decoder.trial", NULL },
+ };
+ static const size_t kNumMimeToRole =
+ sizeof(kFFMPEGMimeToRole) / sizeof(kFFMPEGMimeToRole[0]);
+
+ size_t i;
+ for (i = 0; i < kNumMimeToRole; ++i) {
+ if (!strcasecmp(mime, kFFMPEGMimeToRole[i].mime)) {
+ break;
+ }
+ }
+
+ if (i == kNumMimeToRole) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ const char *role =
+ isEncoder ? kFFMPEGMimeToRole[i].encoderRole
+ : kFFMPEGMimeToRole[i].decoderRole;
+
+ if (role != NULL) {
+ OMX_PARAM_COMPONENTROLETYPE roleParams;
+ InitOMXParams(&roleParams);
+
+ strncpy((char *)roleParams.cRole,
+ role, OMX_MAX_STRINGNAME_SIZE - 1);
+
+ roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ status_t err = omx->setParameter(
+ node, OMX_IndexParamStandardComponentRole,
+ &roleParams, sizeof(roleParams));
+
+ if (err != OK) {
+ ALOGW("Failed to set standard component role '%s'.", role);
+ return err;
+ }
+ }
+ return OK;
+}
+
+//video
+status_t FFMPEGSoftCodec::setWMVFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t version = -1;
+ OMX_VIDEO_PARAM_WMVTYPE paramWMV;
+
+ if (!msg->findInt32(getMsgKey(kKeyWMVVersion), &version)) {
+ ALOGE("WMV version not detected");
+ }
+
+ InitOMXParams(&paramWMV);
+ paramWMV.nPortIndex = kPortIndexInput;
+
+ status_t err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamVideoWmv, &paramWMV, sizeof(paramWMV));
+ if (err != OK) {
+ return err;
+ }
+
+ if (version == kTypeWMVVer_7) {
+ paramWMV.eFormat = OMX_VIDEO_WMVFormat7;
+ } else if (version == kTypeWMVVer_8) {
+ paramWMV.eFormat = OMX_VIDEO_WMVFormat8;
+ } else if (version == kTypeWMVVer_9) {
+ paramWMV.eFormat = OMX_VIDEO_WMVFormat9;
+ }
+
+ err = OMXhandle->setParameter(
+ nodeID, OMX_IndexParamVideoWmv, &paramWMV, sizeof(paramWMV));
+ return err;
+}
+
+status_t FFMPEGSoftCodec::setRVFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t version = kTypeRVVer_G2;
+ OMX_VIDEO_PARAM_RVTYPE paramRV;
+
+ if (!msg->findInt32(getMsgKey(kKeyRVVersion), &version)) {
+ ALOGE("RV version not detected");
+ }
+
+ InitOMXParams(&paramRV);
+ paramRV.nPortIndex = kPortIndexInput;
+
+ status_t err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamVideoRv, &paramRV, sizeof(paramRV));
+ if (err != OK)
+ return err;
+
+ if (version == kTypeRVVer_G2) {
+ paramRV.eFormat = OMX_VIDEO_RVFormatG2;
+ } else if (version == kTypeRVVer_8) {
+ paramRV.eFormat = OMX_VIDEO_RVFormat8;
+ } else if (version == kTypeRVVer_9) {
+ paramRV.eFormat = OMX_VIDEO_RVFormat9;
+ }
+
+ err = OMXhandle->setParameter(
+ nodeID, OMX_IndexParamVideoRv, &paramRV, sizeof(paramRV));
+ return err;
+}
+
+status_t FFMPEGSoftCodec::setFFmpegVideoFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t codec_id = 0;
+ int32_t width = 0;
+ int32_t height = 0;
+ OMX_VIDEO_PARAM_FFMPEGTYPE param;
+
+ ALOGD("setFFmpegVideoFormat");
+
+ if (msg->findInt32(getMsgKey(kKeyWidth), &width)) {
+ ALOGE("No video width specified");
+ }
+ if (msg->findInt32(getMsgKey(kKeyHeight), &height)) {
+ ALOGE("No video height specified");
+ }
+ if (!msg->findInt32(getMsgKey(kKeyCodecId), &codec_id)) {
+ ALOGE("No codec id sent for FFMPEG catch-all codec!");
+ }
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ status_t err = OMXhandle->getParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamVideoFFmpeg, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.eCodecId = codec_id;
+ param.nWidth = width;
+ param.nHeight = height;
+
+ err = OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamVideoFFmpeg, &param, sizeof(param));
+ return err;
+}
+
+//audio
+status_t FFMPEGSoftCodec::setRawAudioFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ int32_t bitsPerSample = 16;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+ if (!msg->findInt32(getMsgKey(kKeyBitsPerSample), &bitsPerSample)) {
+ ALOGD("No PCM format specified, using 16 bit");
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ err = OMXhandle->setParameter(
+ nodeID, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
+ InitOMXParams(&pcmParams);
+ pcmParams.nPortIndex = kPortIndexOutput;
+
+ err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ if (err != OK) {
+ return err;
+ }
+
+ pcmParams.nChannels = numChannels;
+ pcmParams.eNumData = OMX_NumericalDataSigned;
+ pcmParams.bInterleaved = OMX_TRUE;
+ pcmParams.nBitPerSample = bitsPerSample;
+ pcmParams.nSamplingRate = sampleRate;
+ pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
+
+ if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
+ return OMX_ErrorNone;
+ }
+
+ return OMXhandle->setParameter(
+ nodeID, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+}
+
+status_t FFMPEGSoftCodec::setWMAFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t version = 0;
+ int32_t numChannels = 0;
+ int32_t bitRate = 0;
+ int32_t sampleRate = 0;
+ int32_t blockAlign = 0;
+ int32_t bitsPerSample = 0;
+
+ OMX_AUDIO_PARAM_WMATYPE paramWMA;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+ CHECK(msg->findInt32(getMsgKey(kKeyBitRate), &bitRate));
+ if (!msg->findInt32(getMsgKey(kKeyBlockAlign), &blockAlign)) {
+ // we should be last on the codec list, but another sniffer may
+ // have handled it and there is no hardware codec.
+ if (!msg->findInt32(getMsgKey(kKeyWMABlockAlign), &blockAlign)) {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+
+ // mm-parser may want a different bit depth
+ if (msg->findInt32(getMsgKey(kKeyWMABitspersample), &bitsPerSample)) {
+ msg->setInt32("bit-width", bitsPerSample);
+ }
+
+ ALOGV("Channels: %d, SampleRate: %d, BitRate: %d, blockAlign: %d",
+ numChannels, sampleRate, bitRate, blockAlign);
+
+ CHECK(msg->findInt32(getMsgKey(kKeyWMAVersion), &version));
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&paramWMA);
+ paramWMA.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamAudioWma, &paramWMA, sizeof(paramWMA));
+ if (err != OK)
+ return err;
+
+ paramWMA.nChannels = numChannels;
+ paramWMA.nSamplingRate = sampleRate;
+ paramWMA.nBitRate = bitRate;
+ paramWMA.nBlockAlign = blockAlign;
+
+ // http://msdn.microsoft.com/en-us/library/ff819498(v=vs.85).aspx
+ if (version == kTypeWMA) {
+ paramWMA.eFormat = OMX_AUDIO_WMAFormat7;
+ } else if (version == kTypeWMAPro) {
+ paramWMA.eFormat = OMX_AUDIO_WMAFormat8;
+ } else if (version == kTypeWMALossLess) {
+ paramWMA.eFormat = OMX_AUDIO_WMAFormat9;
+ }
+
+ return OMXhandle->setParameter(
+ nodeID, OMX_IndexParamAudioWma, &paramWMA, sizeof(paramWMA));
+}
+
+status_t FFMPEGSoftCodec::setVORBISFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ OMX_AUDIO_PARAM_VORBISTYPE param;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+
+ ALOGV("Channels: %d, SampleRate: %d",
+ numChannels, sampleRate);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamAudioVorbis, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.nChannels = numChannels;
+ param.nSampleRate = sampleRate;
+
+ return OMXhandle->setParameter(
+ nodeID, OMX_IndexParamAudioVorbis, &param, sizeof(param));
+}
+
+status_t FFMPEGSoftCodec::setRAFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t bitRate = 0;
+ int32_t sampleRate = 0;
+ int32_t blockAlign = 0;
+ OMX_AUDIO_PARAM_RATYPE paramRA;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+ msg->findInt32(getMsgKey(kKeyBitRate), &bitRate);
+ CHECK(msg->findInt32(getMsgKey(kKeyBlockAlign), &blockAlign));
+
+ ALOGV("Channels: %d, SampleRate: %d, BitRate: %d, blockAlign: %d",
+ numChannels, sampleRate, bitRate, blockAlign);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&paramRA);
+ paramRA.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamAudioRa, &paramRA, sizeof(paramRA));
+ if (err != OK)
+ return err;
+
+ paramRA.eFormat = OMX_AUDIO_RAFormatUnused; // FIXME, cook only???
+ paramRA.nChannels = numChannels;
+ paramRA.nSamplingRate = sampleRate;
+ // FIXME, HACK!!!, I use the nNumRegions parameter pass blockAlign!!!
+ // the cook audio codec need blockAlign!
+ paramRA.nNumRegions = blockAlign;
+
+ return OMXhandle->setParameter(
+ nodeID, OMX_IndexParamAudioRa, &paramRA, sizeof(paramRA));
+}
+
+status_t FFMPEGSoftCodec::setFLACFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ int32_t bitsPerSample = 16;
+ OMX_AUDIO_PARAM_FLACTYPE param;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+ CHECK(msg->findInt32(getMsgKey(kKeyBitsPerSample), &bitsPerSample));
+
+ ALOGV("Channels: %d, SampleRate: %d BitsPerSample: %d",
+ numChannels, sampleRate, bitsPerSample);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, OMX_IndexParamAudioFlac, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.nChannels = numChannels;
+ param.nSampleRate = sampleRate;
+ param.nCompressionLevel = bitsPerSample; // piggyback hax!
+
+ return OMXhandle->setParameter(
+ nodeID, OMX_IndexParamAudioFlac, &param, sizeof(param));
+}
+
+status_t FFMPEGSoftCodec::setMP2Format(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ OMX_AUDIO_PARAM_MP2TYPE param;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+
+ ALOGV("Channels: %d, SampleRate: %d",
+ numChannels, sampleRate);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioMp2, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.nChannels = numChannels;
+ param.nSampleRate = sampleRate;
+
+ return OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioMp2, &param, sizeof(param));
+}
+
+status_t FFMPEGSoftCodec::setAC3Format(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ OMX_AUDIO_PARAM_ANDROID_AC3TYPE param;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+
+ ALOGV("Channels: %d, SampleRate: %d",
+ numChannels, sampleRate);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.nChannels = numChannels;
+ param.nSampleRate = sampleRate;
+
+ return OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &param, sizeof(param));
+}
+
+status_t FFMPEGSoftCodec::setAPEFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ int32_t bitsPerSample = 0;
+ OMX_AUDIO_PARAM_APETYPE param;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+ CHECK(msg->findInt32(getMsgKey(kKeyBitsPerSample), &bitsPerSample));
+
+ ALOGV("Channels:%d, SampleRate:%d, bitsPerSample:%d",
+ numChannels, sampleRate, bitsPerSample);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioApe, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.nChannels = numChannels;
+ param.nSamplingRate = sampleRate;
+ param.nBitsPerSample = bitsPerSample;
+
+ return OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioApe, &param, sizeof(param));
+}
+
+status_t FFMPEGSoftCodec::setDTSFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t numChannels = 0;
+ int32_t sampleRate = 0;
+ OMX_AUDIO_PARAM_DTSTYPE param;
+
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate));
+
+ ALOGV("Channels: %d, SampleRate: %d",
+ numChannels, sampleRate);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioDts, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.nChannels = numChannels;
+ param.nSamplingRate = sampleRate;
+
+ return OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioDts, &param, sizeof(param));
+}
+
+status_t FFMPEGSoftCodec::setFFmpegAudioFormat(
+ const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID)
+{
+ int32_t codec_id = 0;
+ int32_t numChannels = 0;
+ int32_t bitRate = 0;
+ int32_t bitsPerSample = 16;
+ int32_t sampleRate = 0;
+ int32_t blockAlign = 0;
+ int32_t sampleFormat = 0;
+ int32_t codedSampleBits = 0;
+ OMX_AUDIO_PARAM_FFMPEGTYPE param;
+
+ ALOGD("setFFmpegAudioFormat");
+
+ CHECK(msg->findInt32(getMsgKey(kKeyCodecId), &codec_id));
+ CHECK(msg->findInt32(getMsgKey(kKeyChannelCount), &numChannels));
+ CHECK(msg->findInt32(getMsgKey(kKeySampleFormat), &sampleFormat));
+ msg->findInt32(getMsgKey(kKeyBitRate), &bitRate);
+ msg->findInt32(getMsgKey(kKeyBitsPerSample), &bitsPerSample);
+ msg->findInt32(getMsgKey(kKeySampleRate), &sampleRate);
+ msg->findInt32(getMsgKey(kKeyBlockAlign), &blockAlign);
+ msg->findInt32(getMsgKey(kKeyBitsPerSample), &bitsPerSample);
+ msg->findInt32(getMsgKey(kKeyCodedSampleBits), &codedSampleBits);
+
+ status_t err = setRawAudioFormat(msg, OMXhandle, nodeID);
+ if (err != OK)
+ return err;
+
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexInput;
+
+ err = OMXhandle->getParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioFFmpeg, &param, sizeof(param));
+ if (err != OK)
+ return err;
+
+ param.eCodecId = codec_id;
+ param.nChannels = numChannels;
+ param.nBitRate = bitRate;
+ param.nBitsPerSample = codedSampleBits;
+ param.nSampleRate = sampleRate;
+ param.nBlockAlign = blockAlign;
+ param.eSampleFormat = sampleFormat;
+
+ return OMXhandle->setParameter(
+ nodeID, (OMX_INDEXTYPE)OMX_IndexParamAudioFFmpeg, &param, sizeof(param));
+}
+
+}
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 565f156..f7b1a02 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -30,6 +30,7 @@ namespace android {
FileSource::FileSource(const char *filename)
: mFd(-1),
+ mUri(filename),
mOffset(0),
mLength(-1),
mDecryptHandle(NULL),
@@ -58,6 +59,7 @@ FileSource::FileSource(int fd, int64_t offset, int64_t length)
mDrmBuf(NULL){
CHECK(offset >= 0);
CHECK(length >= 0);
+ fetchUriFromFd(fd);
}
FileSource::~FileSource() {
@@ -188,4 +190,18 @@ ssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) {
return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
}
}
+
+void FileSource::fetchUriFromFd(int fd) {
+ ssize_t len = 0;
+ char path[PATH_MAX] = {0};
+ char link[PATH_MAX] = {0};
+
+ mUri.clear();
+
+ snprintf(path, PATH_MAX, "/proc/%d/fd/%d", getpid(), fd);
+ if ((len = readlink(path, link, sizeof(link)-1)) != -1) {
+ link[len] = '\0';
+ mUri.setTo(link);
+ }
+}
} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7f7c7fa..b74836f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1143,7 +1143,8 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
CHECK(msg->findString("componentName", &mComponentName));
- if (mComponentName.startsWith("OMX.google.")) {
+ if (mComponentName.startsWith("OMX.google.") ||
+ mComponentName.startsWith("OMX.ffmpeg.")) {
mFlags |= kFlagUsesSoftwareRenderer;
} else {
mFlags &= ~kFlagUsesSoftwareRenderer;
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 2a50692..089c150 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -64,4 +64,32 @@ const char *MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
const char *MEDIA_MIMETYPE_TEXT_CEA_608 = "text/cea-608";
const char *MEDIA_MIMETYPE_DATA_TIMED_ID3 = "application/x-id3v4";
+const char *MEDIA_MIMETYPE_VIDEO_FLV1 = "video/x-flv";
+const char *MEDIA_MIMETYPE_VIDEO_MJPEG = "video/x-jpeg";
+const char *MEDIA_MIMETYPE_VIDEO_RV = "video/vnd.rn-realvideo";
+const char *MEDIA_MIMETYPE_VIDEO_VC1 = "video/vc1";
+const char *MEDIA_MIMETYPE_VIDEO_FFMPEG = "video/ffmpeg";
+
+const char *MEDIA_MIMETYPE_AUDIO_PCM = "audio/x-pcm";
+const char *MEDIA_MIMETYPE_AUDIO_RA = "audio/vnd.rn-realaudio";
+const char *MEDIA_MIMETYPE_AUDIO_FFMPEG = "audio/ffmpeg";
+
+const char *MEDIA_MIMETYPE_CONTAINER_APE = "audio/x-ape";
+const char *MEDIA_MIMETYPE_CONTAINER_DIVX = "video/divx";
+const char *MEDIA_MIMETYPE_CONTAINER_DTS = "audio/vnd.dts";
+const char *MEDIA_MIMETYPE_CONTAINER_FLAC = "audio/flac";
+const char *MEDIA_MIMETYPE_CONTAINER_FLV = "video/x-flv";
+const char *MEDIA_MIMETYPE_CONTAINER_MOV = "video/quicktime";
+const char *MEDIA_MIMETYPE_CONTAINER_MP2 = "audio/mpeg2";
+const char *MEDIA_MIMETYPE_CONTAINER_MPG = "video/mpeg";
+const char *MEDIA_MIMETYPE_CONTAINER_RA = "audio/vnd.rn-realaudio";
+const char *MEDIA_MIMETYPE_CONTAINER_RM = "video/vnd.rn-realvideo";
+const char *MEDIA_MIMETYPE_CONTAINER_TS = "video/mp2t";
+const char *MEDIA_MIMETYPE_CONTAINER_WEBM = "video/webm";
+const char *MEDIA_MIMETYPE_CONTAINER_WMA = "audio/x-ms-wma";
+const char *MEDIA_MIMETYPE_CONTAINER_WMV = "video/x-ms-wmv";
+const char *MEDIA_MIMETYPE_CONTAINER_VC1 = "video/vc1";
+const char *MEDIA_MIMETYPE_CONTAINER_HEVC = "video/hevc";
+const char *MEDIA_MIMETYPE_CONTAINER_FFMPEG = "video/ffmpeg";
+
} // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 0f656a1..fc43d43 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -44,6 +44,8 @@
namespace android {
+MediaExtractor::Plugin MediaExtractor::sPlugin;
+
sp<MetaData> MediaExtractor::getMetaData() {
return new MetaData;
}
@@ -57,9 +59,15 @@ sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
sp<AMessage> meta;
+ bool secondPass = false;
+
String8 tmp;
- if (mime == NULL) {
+retry:
+ if (secondPass || mime == NULL) {
float confidence;
+ if (secondPass) {
+ confidence = 3.14f;
+ }
if (!source->sniff(&tmp, &confidence, &meta)) {
ALOGV("FAILED to autodetect media content.");
@@ -94,7 +102,12 @@ sp<MediaExtractor> MediaExtractor::Create(
}
sp<MediaExtractor> ret = NULL;
+ AString extractorName;
if ((ret = AVFactory::get()->createExtendedExtractor(source, mime, meta)) != NULL) {
+ } else if (meta.get() && meta->findString("extended-extractor-use", &extractorName)
+ && sPlugin.create) {
+ ALOGI("Use extended extractor for the special mime(%s) or codec", mime);
+ ret = sPlugin.create(source, mime, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
|| !strcasecmp(mime, "audio/mp4")) {
ret = new MPEG4Extractor(source);
@@ -122,6 +135,8 @@ sp<MediaExtractor> MediaExtractor::Create(
ret = new MPEG2PSExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MIDI)) {
ret = new MidiExtractor(source);
+ } else if (!isDrm && sPlugin.create) {
+ ret = sPlugin.create(source, mime, meta);
}
ret = AVFactory::get()->updateExtractor(ret, source, mime, meta);
@@ -133,6 +148,15 @@ sp<MediaExtractor> MediaExtractor::Create(
}
}
+ if (ret != NULL) {
+
+ if (!secondPass && ( ret->countTracks() == 0 ||
+ (!strncasecmp("video/", mime, 6) && ret->countTracks() < 2) ) ) {
+ secondPass = true;
+ goto retry;
+ }
+ }
+
return ret;
}
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index e69890d..ac925f7 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -181,6 +181,7 @@ bool MuxOMX::isLocalNode_l(node_id node) const {
}
// static
+
bool MuxOMX::CanLiveLocally(const char *name) {
#ifdef __LP64__
(void)name; // disable unused parameter warning
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index a757181..c5018ae 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -42,7 +42,11 @@ static bool FileHasAcceptableExtension(const char *extension) {
".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
- ".avi", ".mpeg", ".mpg", ".awb", ".mpga"
+ ".adts", ".dm", ".m2ts", ".mp3d", ".wmv", ".asf", ".flv",
+ ".mov", ".ra", ".rm", ".rmvb", ".ac3", ".ape", ".dts",
+ ".mp1", ".mp2", ".f4v", "hlv", "nrg", "m2v", ".swf",
+ ".avi", ".mpg", ".mpeg", ".awb", ".vc1", ".vob", ".divx",
+ ".mpga", ".mov", ".qcp", ".ec3"
};
static const size_t kNumValidExtensions =
sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index e7d36dc..d7b0bad 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -36,6 +36,7 @@
#include <media/AudioParameter.h>
#include <stagefright/AVExtensions.h>
+#include <media/stagefright/FFMPEGSoftCodec.h>
namespace android {
@@ -106,7 +107,7 @@ status_t convertMetaDataToMessage(
int avgBitRate;
if (meta->findInt32(kKeyBitRate, &avgBitRate)) {
- msg->setInt32("bit-rate", avgBitRate);
+ msg->setInt32("bitrate", avgBitRate);
}
int32_t isSync;
@@ -205,6 +206,11 @@ status_t convertMetaDataToMessage(
msg->setInt32("frame-rate", fps);
}
+ int32_t bitsPerSample;
+ if (meta->findInt32(kKeyBitsPerSample, &bitsPerSample)) {
+ msg->setInt32("bit-width", bitsPerSample);
+ }
+
uint32_t type;
const void *data;
size_t size;
@@ -300,7 +306,7 @@ status_t convertMetaDataToMessage(
const uint8_t *ptr = (const uint8_t *)data;
CHECK(size >= 7);
- CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+ //CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
uint8_t profile __unused = ptr[1] & 31;
uint8_t level __unused = ptr[12];
ptr += 22;
@@ -436,8 +442,14 @@ status_t convertMetaDataToMessage(
}
AVUtils::get()->convertMetaDataToMessage(meta, &msg);
+
+ FFMPEGSoftCodec::convertMetaDataToMessageFF(meta, &msg);
*format = msg;
+ ALOGI("convertMetaDataToMessage from:");
+ meta->dumpToLog();
+ ALOGI(" to: %s", msg->debugString(0).c_str());
+
return OK;
}
@@ -629,6 +641,11 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
if (msg->findInt32("is-adts", &isADTS)) {
meta->setInt32(kKeyIsADTS, isADTS);
}
+
+ int32_t bitsPerSample;
+ if (msg->findInt32("bit-width", &bitsPerSample)) {
+ meta->setInt32(kKeyBitsPerSample, bitsPerSample);
+ }
}
int32_t maxInputSize;
@@ -680,10 +697,10 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
// XXX TODO add whatever other keys there are
-#if 0
- ALOGI("converted %s to:", msg->debugString(0).c_str());
+ FFMPEGSoftCodec::convertMessageToMetaDataFF(msg, meta);
+
+ ALOGI("convertMessageToMetaData from %s to:", msg->debugString(0).c_str());
meta->dumpToLog();
-#endif
}
AString MakeUserAgent() {
@@ -829,6 +846,7 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo,
if (AVUtils::get()->canOffloadAPE(meta) != true) {
return false;
}
+ ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info.format);
// Redefine aac format according to its profile
// Offloading depends on audio DSP capabilities.
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index b78b36f..0d80098 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -42,7 +42,8 @@ SoftRaw::SoftRaw(
: SimpleSoftOMXComponent(name, callbacks, appData, component),
mSignalledError(false),
mChannelCount(2),
- mSampleRate(44100) {
+ mSampleRate(44100),
+ mBitsPerSample(16) {
initPorts();
CHECK_EQ(initDecoder(), (status_t)OK);
}
@@ -110,7 +111,7 @@ OMX_ERRORTYPE SoftRaw::internalGetParameter(
pcmParams->eNumData = OMX_NumericalDataSigned;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -154,6 +155,7 @@ OMX_ERRORTYPE SoftRaw::internalSetParameter(
mChannelCount = pcmParams->nChannels;
mSampleRate = pcmParams->nSamplingRate;
+ mBitsPerSample = pcmParams->nBitPerSample;
return OMX_ErrorNone;
}
diff --git a/media/libstagefright/codecs/raw/SoftRaw.h b/media/libstagefright/codecs/raw/SoftRaw.h
index 94b0ef1..894889f 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.h
+++ b/media/libstagefright/codecs/raw/SoftRaw.h
@@ -50,6 +50,7 @@ private:
int32_t mChannelCount;
int32_t mSampleRate;
+ int32_t mBitsPerSample;
void initPorts();
status_t initDecoder();
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 758b2c9..c72f9f6 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -193,6 +193,7 @@ private:
uint32_t mFlags;
uint32_t mExtractorFlags;
uint32_t mSinceLastDropped;
+ bool mDropFramesDisable; // hevc test
int64_t mTimeSourceDeltaUs;
int64_t mVideoTimeUs;
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index a66ca6d..ff81379 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -240,13 +240,12 @@ MatroskaSource::MatroskaSource(
mType = HEVC;
uint32_t type;
- const void *data;
+ const uint8_t *data;
size_t size;
- CHECK(meta->findData(kKeyHVCC, &type, &data, &size));
+ CHECK(meta->findData(kKeyHVCC, &type, (const void **)&data, &size));
- const uint8_t *ptr = (const uint8_t *)data;
CHECK(size >= 7);
- mNALSizeLen = 1 + (ptr[14 + 7] & 3);
+ mNALSizeLen = 1 + (data[14 + 7] & 3);
ALOGV("mNALSizeLen = %zu", mNALSizeLen);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
mType = AAC;
@@ -1028,7 +1027,7 @@ void MatroskaExtractor::addTracks() {
}
} else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) {
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
- meta->setData(kKeyHVCC, 0, codecPrivate, codecPrivateSize);
+ meta->setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
} else if (!strcmp("V_VP8", codecID)) {
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
@@ -1051,7 +1050,9 @@ void MatroskaExtractor::addTracks() {
if (!strcmp("A_AAC", codecID)) {
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
- CHECK(codecPrivateSize >= 2);
+ if (codecPrivateSize < 2) {
+ return;
+ }
addESDSFromCodecPrivate(
meta, true, codecPrivate, codecPrivateSize);
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 7165c6c..f0ae4ec 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -137,6 +137,7 @@ public:
case AUDIO_FORMAT_PCM_8_BIT:
case AUDIO_FORMAT_PCM_16_BIT:
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ case AUDIO_FORMAT_PCM_8_24_BIT:
case AUDIO_FORMAT_PCM_32_BIT:
case AUDIO_FORMAT_PCM_FLOAT:
return true;