summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorST-Ericsson <void@stericsson.com>2012-04-20 13:39:45 +0200
committerPatrik Ryd <patrik.ryd@linaro.org>2012-05-09 19:13:01 +0200
commit7fcc59be0ba1d2d9404278903694b966a3a30629 (patch)
treed2e8b6e8538c9f4e3312cd2eede89fe19ce64fd7
parent681fc12b00cabc77d8ae9b539a286c50408d7cc1 (diff)
downloadbase-7fcc59be0ba1d2d9404278903694b966a3a30629.tar.gz
Adding multimedia extension
More specifically: - Add support for ST-Ericsson native pixel formats and conversion to and from these formats. - The Khronos headers are out of date and Mali extensions are missing from the extension headers. GLES2/gl2ext.h has been updated with the missing ARM extensions. - ST-Ericsson audio support for multimedia. - ST-Ericsson video support for multimedia. - Support for FM Audio in framework. Signed-off-by: Patrik Ryd <patrik.ryd@stericsson.com> (cherry picked from commit b5650a283cd3b95f9d4eb1b39dc031f1e2dc82da) Change-Id: I5c899aaaa567cf6c40508e3eaad871518d370e11 Signed-off-by: Patrik Ryd <patrik.ryd@linaro.org>
-rw-r--r--api/current.txt1
-rw-r--r--core/jni/Android.mk4
-rw-r--r--include/camera/CameraParameters.h11
-rw-r--r--include/gui/SurfaceTexture.h47
-rw-r--r--include/media/AudioSystem.h4
-rw-r--r--include/media/AudioTrack.h1
-rw-r--r--include/media/IAudioFlinger.h6
-rw-r--r--include/media/IAudioPolicyService.h3
-rw-r--r--include/media/stagefright/AudioPlayer.h1
-rw-r--r--include/media/stagefright/ColorConverter.h3
-rw-r--r--include/media/stagefright/FMRadioDataSource.h73
-rw-r--r--include/media/stagefright/MediaDefs.h2
-rw-r--r--include/media/stagefright/OMXCodec.h1
-rw-r--r--include/media/stagefright/foundation/ABitReader.h4
-rw-r--r--include/media/stagefright/openmax/OMX_IVCommon.h1
-rw-r--r--include/ui/PixelFormat.h6
-rw-r--r--include/ui/Region.h22
-rw-r--r--libs/camera/Android.mk4
-rw-r--r--libs/camera/CameraParameters.cpp12
-rw-r--r--libs/gui/Android.mk4
-rw-r--r--libs/gui/SurfaceTexture.cpp216
-rw-r--r--libs/ui/Android.mk4
-rw-r--r--libs/ui/PixelFormat.cpp10
-rw-r--r--media/java/android/media/MediaPlayer.java3
-rw-r--r--media/java/android/media/MediaRecorder.java2
-rw-r--r--media/libmedia/Android.mk16
-rw-r--r--media/libmedia/AudioSystem.cpp6
-rw-r--r--media/libmedia/IAudioFlinger.cpp42
-rw-r--r--media/libmedia/IAudioPolicyService.cpp9
-rw-r--r--media/libmediaplayerservice/Android.mk4
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp2
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h1
-rw-r--r--media/libstagefright/Android.mk6
-rw-r--r--media/libstagefright/AwesomePlayer.cpp14
-rw-r--r--[-rwxr-xr-x]media/libstagefright/CameraSource.cpp11
-rw-r--r--media/libstagefright/DataSource.cpp2
-rw-r--r--media/libstagefright/FMRadioDataSource.cpp100
-rw-r--r--[-rwxr-xr-x]media/libstagefright/MPEG4Writer.cpp0
-rw-r--r--media/libstagefright/MediaDefs.cpp2
-rw-r--r--media/libstagefright/MediaExtractor.cpp3
-rw-r--r--[-rwxr-xr-x]media/libstagefright/OMXCodec.cpp55
-rw-r--r--media/libstagefright/PCMExtractor.cpp276
-rw-r--r--media/libstagefright/colorconversion/Android.mk4
-rw-r--r--media/libstagefright/colorconversion/ColorConverter.cpp142
-rw-r--r--media/libstagefright/foundation/ABitReader.cpp15
-rw-r--r--media/libstagefright/foundation/Android.mk4
-rw-r--r--media/libstagefright/include/PCMExtractor.h68
-rw-r--r--media/libstagefright/omx/Android.mk4
-rw-r--r--media/libstagefright/omx/SoftOMXPlugin.cpp2
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp77
-rw-r--r--media/libstagefright/rtsp/Android.mk8
-rw-r--r--opengl/include/EGL/eglext.h12
-rw-r--r--opengl/include/GLES2/gl2ext.h26
-rw-r--r--opengl/libs/EGL/eglApi.cpp83
-rw-r--r--opengl/libs/EGL/egl_entries.in4
-rw-r--r--services/audioflinger/Android.mk4
-rw-r--r--services/audioflinger/AudioFlinger.cpp71
-rw-r--r--services/audioflinger/AudioFlinger.h8
-rw-r--r--services/audioflinger/AudioPolicyService.cpp14
-rw-r--r--services/audioflinger/AudioPolicyService.h3
-rw-r--r--services/surfaceflinger/Android.mk4
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp2
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp1
-rw-r--r--services/surfaceflinger/Layer.cpp12
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp59
65 files changed, 1421 insertions, 200 deletions
diff --git a/api/current.txt b/api/current.txt
index 506ab35d11cb..cc8706a3e68d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10860,6 +10860,7 @@ package android.media {
public final class MediaRecorder.AudioSource {
field public static final int CAMCORDER = 5; // 0x5
field public static final int DEFAULT = 0; // 0x0
+ field public static final int FM_RADIO_RX = 8; // 0x8
field public static final int MIC = 1; // 0x1
field public static final int VOICE_CALL = 4; // 0x4
field public static final int VOICE_COMMUNICATION = 7; // 0x7
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 93fd5fb0d449..550722c6a22e 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -24,6 +24,10 @@ ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER
endif
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_SRC_FILES:= \
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 7edf6b4562ff..e0bba334575d 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -596,9 +596,15 @@ public:
// Pixel color formats for KEY_PREVIEW_FORMAT, KEY_PICTURE_FORMAT,
// and KEY_VIDEO_FRAME_FORMAT
static const char PIXEL_FORMAT_YUV422SP[];
+ static const char PIXEL_FORMAT_YUV420P[]; // YV12
static const char PIXEL_FORMAT_YUV420SP[]; // NV21
+ static const char PIXEL_FORMAT_YUV420SPNV12[]; // NV12
static const char PIXEL_FORMAT_YUV422I[]; // YUY2
- static const char PIXEL_FORMAT_YUV420P[]; // YV12
+ static const char PIXEL_FORMAT_YVU422SP[];
+ static const char PIXEL_FORMAT_YVU422P[];
+ static const char PIXEL_FORMAT_YVU420SP[];
+ static const char PIXEL_FORMAT_YVU420P[];
+ static const char PIXEL_FORMAT_YUV420MB[];
static const char PIXEL_FORMAT_RGB565[];
static const char PIXEL_FORMAT_RGBA8888[];
static const char PIXEL_FORMAT_JPEG[];
@@ -656,6 +662,9 @@ public:
// To stop continuous focus, applications should change the focus mode to
// other modes.
static const char FOCUS_MODE_CONTINUOUS_PICTURE[];
+ // keys for record stride and slice height
+ static const char KEY_RECORD_STRIDE[];
+ static const char KEY_RECORD_SLICE_HEIGHT[];
private:
DefaultKeyedVector<String8,String8> mMap;
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index a8c76725e7c9..a8db994988fc 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -29,7 +29,7 @@
#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/threads.h>
-
+#include <hardware/copybit.h>
#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
namespace android {
@@ -47,6 +47,7 @@ public:
};
enum { NUM_BUFFER_SLOTS = 32 };
enum { NO_CONNECTED_API = 0 };
+ enum { NUM_BLIT_BUFFER_SLOTS = 2 };
struct FrameAvailableListener : public virtual RefBase {
// onFrameAvailable() is called from queueBuffer() each time an
@@ -139,6 +140,16 @@ public:
// target texture belongs is bound to the calling thread.
status_t updateTexImage();
+ // A surface that uses a non-native format requires conversion of
+ // its buffers. This conversion can be deferred until the layer
+ // based on this surface is drawn.
+ status_t updateTexImage(bool deferConversion);
+
+ // convert() performs the deferred texture conversion as scheduled
+ // by updateTexImage(bool deferConversion).
+ // The method returns immediately if no conversion is necessary.
+ status_t convert();
+
// setBufferCountServer set the buffer count. If the client has requested
// a buffer count using setBufferCount, the server-buffer count will
// take effect once the client sets the count back to zero.
@@ -263,6 +274,12 @@ private:
EGLImageKHR createImage(EGLDisplay dpy,
const sp<GraphicBuffer>& graphicBuffer);
+ // returns TRUE if buffer needs color format conversion
+ bool conversionIsNeeded(const sp<GraphicBuffer>& graphicBuffer);
+
+ // converts buffer to a suitable color format
+ status_t convert(sp<GraphicBuffer> &srcBuf, sp<GraphicBuffer> &dstBuf);
+
status_t setBufferCountServerLocked(int bufferCount);
// computeCurrentTransformMatrix computes the transform matrix for the
@@ -508,7 +525,33 @@ private:
// with the surface Texture.
uint64_t mFrameCounter;
-
+ // mBlitEngine is the handle to the copybit device which will be used in
+ // case color transform is needed before the EGL image is created.
+ copybit_device_t* mBlitEngine;
+
+ // mBlitSlots contains several buffers which will
+ // be rendered alternately in case color transform is needed (instead
+ // of rendering the buffers in mSlots).
+ BufferSlot mBlitSlots[NUM_BLIT_BUFFER_SLOTS];
+
+ // mNextBlitSlot is the index of the blitter buffer (in mBlitSlots) which
+ // will be used in the next color transform.
+ int mNextBlitSlot;
+
+ // mConversionSrcSlot designates the slot where source buffer
+ // for the last deferred updateTexImage is located.
+ int mConversionSrcSlot;
+
+ // mConversionBltSlot designates the slot where destination buffer
+ // for the last deferred updateTexImage is located.
+ int mConversionBltSlot;
+
+ // mNeedsConversion indicates that a format conversion is necessary
+ // before the layer based on this surface is drawn.
+ // This flag is set whenever updateTexImage() with deferred conversion
+ // is called. It is cleared once the layer is drawn,
+ // or when updateTexImage() w/o deferred conversion is called.
+ bool mNeedsConversion;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 6a15f6ec90a6..95d539efec8c 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -110,7 +110,6 @@ public:
static int newAudioSessionId();
static void acquireAudioSessionId(int audioSession);
static void releaseAudioSessionId(int audioSession);
-
// types of io configuration change events received with ioConfigChanged()
enum io_config_event {
OUTPUT_OPENED,
@@ -163,7 +162,8 @@ public:
uint32_t format = AUDIO_FORMAT_DEFAULT,
uint32_t channels = AUDIO_CHANNEL_IN_MONO,
audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
- int sessionId = 0);
+ int sessionId = 0,
+ audio_input_clients *inputClientId = NULL);
static status_t startInput(audio_io_handle_t input);
static status_t stopInput(audio_io_handle_t input);
static void releaseInput(audio_io_handle_t input);
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 1c401e2b276b..62516c6c54a0 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -451,7 +451,6 @@ private:
status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount);
audio_io_handle_t getOutput_l();
status_t restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart);
-
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
sp<AudioTrackThread> mAudioTrackThread;
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 9e3cb7f3c383..4e72448d330a 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -126,8 +126,9 @@ public:
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
- uint32_t acoustics) = 0;
- virtual status_t closeInput(int input) = 0;
+ uint32_t acoustics,
+ uint32_t *pInputClientId = NULL) = 0;
+ virtual status_t closeInput(int input, uint32_t* inputClientId = NULL) = 0;
virtual status_t setStreamOutput(uint32_t stream, int output) = 0;
@@ -159,6 +160,7 @@ public:
int *enabled) = 0;
virtual status_t moveEffects(int session, int srcOutput, int dstOutput) = 0;
+ virtual size_t readInput(uint32_t *input, uint32_t inputClientId, void *buffer, uint32_t bytes, uint32_t *pOverwrittenBytes) = 0;
};
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 9807cbe56430..1607bc5cdddf 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -66,7 +66,8 @@ public:
uint32_t format = AUDIO_FORMAT_DEFAULT,
uint32_t channels = 0,
audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
- int audioSession = 0) = 0;
+ int audioSession = 0,
+ audio_input_clients *inputClientId = NULL) = 0;
virtual status_t startInput(audio_io_handle_t input) = 0;
virtual status_t stopInput(audio_io_handle_t input) = 0;
virtual void releaseInput(audio_io_handle_t input) = 0;
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 0b79324db69d..ae5937d469aa 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -101,7 +101,6 @@ private:
static size_t AudioSinkCallback(
MediaPlayerBase::AudioSink *audioSink,
void *data, size_t size, void *me);
-
size_t fillBuffer(void *data, size_t size);
int64_t getRealTimeUsLocked() const;
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
index 85ba9206835c..0f9e40051872 100644
--- a/include/media/stagefright/ColorConverter.h
+++ b/include/media/stagefright/ColorConverter.h
@@ -73,6 +73,9 @@ private:
status_t convertQCOMYUV420SemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertSTEYUV420PackedSemiPlanarMB(
+ const BitmapParams &src, const BitmapParams &dst);
+
status_t convertYUV420SemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
diff --git a/include/media/stagefright/FMRadioDataSource.h b/include/media/stagefright/FMRadioDataSource.h
new file mode 100644
index 000000000000..96735550d846
--- /dev/null
+++ b/include/media/stagefright/FMRadioDataSource.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andreas Gustafsson (andreas.a.gustafsson@stericsson.com)
+ * for ST-Ericsson
+ */
+
+#ifndef FMRADIO_DATA_SOURCE_H_
+
+#define FMRADIO_DATA_SOURCE_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+#include <hardware_legacy/AudioHardwareInterface.h>
+#include <media/AudioSystem.h>
+#include <system/audio.h>
+#include <hardware_legacy/AudioSystemLegacy.h>
+
+namespace android {
+
+class FMRadioDataSource : public DataSource {
+public:
+ FMRadioDataSource();
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off64_t *size);
+
+ virtual uint32_t getBufferSize();
+
+ virtual uint32_t getNumChannels();
+
+ virtual uint32_t getSampleRate();
+
+ virtual uint32_t getFormat();
+
+protected:
+ virtual ~FMRadioDataSource();
+
+private:
+ android_audio_legacy::AudioStreamIn *mStream;
+ sp<IAudioFlinger> mAudioFlinger;
+ FMRadioDataSource(const FMRadioDataSource &);
+ FMRadioDataSource &operator=(const FMRadioDataSource &);
+ audio_input_clients mInputClientId;
+ uint32_t mFormat;
+ uint32_t mChannels;
+ uint32_t mSampleRate;
+ uint32_t mOverwrittenBytes;
+ uint32_t mFlags;
+};
+
+} // namespace android
+
+#endif // FMRADIO_DATA_SOURCE_H_
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 2eb259e8b590..a533ed43e1a7 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -26,8 +26,10 @@ extern const char *MEDIA_MIMETYPE_VIDEO_VPX;
extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
extern const char *MEDIA_MIMETYPE_VIDEO_H263;
+extern const char *MEDIA_MIMETYPE_VIDEO_H263_SW;
extern const char *MEDIA_MIMETYPE_VIDEO_MPEG2;
extern const char *MEDIA_MIMETYPE_VIDEO_RAW;
+extern const char *MEDIA_MIMETYPE_VIDEO_VC1;
extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB;
extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 84f8282f64b7..5ebba96c9b57 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -140,6 +140,7 @@ private:
kAvoidMemcopyInputRecordingFrames = 2048,
kRequiresLargerEncoderOutputBuffer = 4096,
kOutputBuffersAreUnreadable = 8192,
+ kRequiresStoreMetaDataBeforeIdle = 16384,
};
enum BufferStatus {
diff --git a/include/media/stagefright/foundation/ABitReader.h b/include/media/stagefright/foundation/ABitReader.h
index 5510b12aee8c..7a4270d53578 100644
--- a/include/media/stagefright/foundation/ABitReader.h
+++ b/include/media/stagefright/foundation/ABitReader.h
@@ -31,6 +31,8 @@ struct ABitReader {
uint32_t getBits(size_t n);
void skipBits(size_t n);
+ void rewindBits(size_t n);
+
void putBits(uint32_t x, size_t n);
size_t numBitsLeft() const;
@@ -39,7 +41,9 @@ struct ABitReader {
private:
const uint8_t *mData;
+ const uint8_t *mOriginalData;
size_t mSize;
+ size_t mOriginalSize;
uint32_t mReservoir; // left-aligned bits
size_t mNumBitsLeft;
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 8bb4dede8fda..5df525c66782 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -159,6 +159,7 @@ typedef enum OMX_COLOR_FORMATTYPE {
OMX_COLOR_FormatAndroidOpaque = 0x7F000789,
OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
+ OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB = 0x7FA00000,
OMX_COLOR_FormatMax = 0x7FFFFFFF
} OMX_COLOR_FORMATTYPE;
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index 848c5a114907..e22071b541de 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -72,6 +72,12 @@ enum {
// New formats can be added if they're also defined in
// pixelflinger/format.h
+
+ // Added Support for YUV42XMBN,
+ // Required for Copybit CC acceleration
+ PIXEL_FORMAT_YCBCR42XMBN = HAL_PIXEL_FORMAT_YCBCR42XMBN,
+ PIXEL_FORMAT_YCbCr_420_SP = HAL_PIXEL_FORMAT_YCbCr_420_SP,
+ PIXEL_FORMAT_YCbCr_420_P = HAL_PIXEL_FORMAT_YCbCr_420_P,
};
typedef int32_t PixelFormat;
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 6c9a6203e793..9ce8efb5579c 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -24,6 +24,8 @@
#include <ui/Rect.h>
+#include <hardware/copybit.h>
+
namespace android {
// ---------------------------------------------------------------------------
@@ -181,6 +183,26 @@ Region& Region::operator -= (const Region& rhs) {
Region& Region::operator += (const Point& pt) {
return translateSelf(pt.x, pt.y);
}
+
+// ---------------------------------------------------------------------------
+
+struct region_iterator : public copybit_region_t {
+ region_iterator(const Region& region)
+ : b(region.begin()), e(region.end()) {
+ this->next = iterate;
+ }
+private:
+ static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+ region_iterator const* me = static_cast<region_iterator const*>(self);
+ if (me->b != me->e) {
+ *reinterpret_cast<Rect*>(rect) = *me->b++;
+ return 1;
+ }
+ return 0;
+ }
+ mutable Region::const_iterator b;
+ Region::const_iterator const e;
+};
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index 7286f9295660..63abad2f46eb 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -1,6 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
Camera.cpp \
CameraParameters.cpp \
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index c6087b404667..4bd6318e122a 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -148,9 +148,15 @@ const char CameraParameters::SCENE_MODE_CANDLELIGHT[] = "candlelight";
const char CameraParameters::SCENE_MODE_BARCODE[] = "barcode";
const char CameraParameters::PIXEL_FORMAT_YUV422SP[] = "yuv422sp";
+const char CameraParameters::PIXEL_FORMAT_YUV420P[] = "yuv420p";
const char CameraParameters::PIXEL_FORMAT_YUV420SP[] = "yuv420sp";
+const char CameraParameters::PIXEL_FORMAT_YUV420SPNV12[] = "yuv420spnv12";
const char CameraParameters::PIXEL_FORMAT_YUV422I[] = "yuv422i-yuyv";
-const char CameraParameters::PIXEL_FORMAT_YUV420P[] = "yuv420p";
+const char CameraParameters::PIXEL_FORMAT_YUV420MB[] = "yuv420mb";
+const char CameraParameters::PIXEL_FORMAT_YVU422SP[] = "yvu422sp";
+const char CameraParameters::PIXEL_FORMAT_YVU422P[] = "yvu422p";
+const char CameraParameters::PIXEL_FORMAT_YVU420SP[] = "yvu420sp";
+const char CameraParameters::PIXEL_FORMAT_YVU420P[] = "yvu420p";
const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
const char CameraParameters::PIXEL_FORMAT_RGBA8888[] = "rgba8888";
const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg";
@@ -165,6 +171,10 @@ const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
const char CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE[] = "continuous-picture";
+// keys for record stride and sliceheight
+const char CameraParameters::KEY_RECORD_STRIDE[] = "record-stride";
+const char CameraParameters::KEY_RECORD_SLICE_HEIGHT[] = "record-slice-height";
+
CameraParameters::CameraParameters()
: mMap()
{
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 9767568bed35..e79cd913e42a 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -1,6 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
ISensorEventConnection.cpp \
ISensorServer.cpp \
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 4772189b7fb4..e32df27f537e 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -28,6 +28,7 @@
#include <gui/SurfaceTexture.h>
#include <hardware/hardware.h>
+#include <ui/PixelFormat.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
@@ -138,6 +139,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
mUseFenceSync(false),
#endif
mTexTarget(texTarget),
+ mNextBlitSlot(0),
+ mNeedsConversion(false),
mFrameCounter(0) {
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
@@ -148,11 +151,26 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
mNextCrop.makeInvalid();
memcpy(mCurrentTransformMatrix, mtxIdentity,
sizeof(mCurrentTransformMatrix));
+
+ for (int i = 0; i < NUM_BLIT_BUFFER_SLOTS; i++) {
+ mBlitSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+ mBlitSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+ }
+
+ hw_module_t const* module;
+ mBlitEngine = 0;
+ if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+ copybit_open(module, &mBlitEngine);
+ }
+ LOGE_IF(!mBlitEngine, "\nCannot open copybit mBlitEngine=%p", mBlitEngine);
}
SurfaceTexture::~SurfaceTexture() {
ST_LOGV("~SurfaceTexture");
freeAllBuffersLocked();
+ if (mBlitEngine) {
+ copybit_close(mBlitEngine);
+ }
}
status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
@@ -747,6 +765,11 @@ status_t SurfaceTexture::setScalingMode(int mode) {
}
status_t SurfaceTexture::updateTexImage() {
+ return updateTexImage(false);
+}
+
+#define STE_DEFERDBG 0
+status_t SurfaceTexture::updateTexImage(bool deferConversion) {
ST_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
@@ -762,20 +785,99 @@ status_t SurfaceTexture::updateTexImage() {
int buf = *front;
// Update the GL texture object.
- EGLImageKHR image = mSlots[buf].mEglImage;
+ EGLImageKHR image;
EGLDisplay dpy = eglGetCurrentDisplay();
- if (image == EGL_NO_IMAGE_KHR) {
- if (mSlots[buf].mGraphicBuffer == 0) {
- ST_LOGE("buffer at slot %d is null", buf);
- return BAD_VALUE;
+ sp<GraphicBuffer> graphicBuffer;
+ if (conversionIsNeeded(mSlots[buf].mGraphicBuffer)) {
+ mNeedsConversion = deferConversion;
+ // If color conversion is needed we can't use the graphic buffers
+ // located in mSlots for the textures (wrong color format). Instead
+ // color convert it into a buffer in mBlitSlots and use that instead.
+ image = mBlitSlots[mNextBlitSlot].mEglImage;
+
+ // If there exists an image already, make sure that
+ // the dimensions match the current source buffer.
+ // Otherwise, destroy the buffer and let a new one be allocated.
+ if (image != EGL_NO_IMAGE_KHR &&
+ mSlots[buf].mGraphicBuffer != NULL &&
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer != NULL) {
+ sp<GraphicBuffer> &srcBuf = mSlots[buf].mGraphicBuffer;
+ sp<GraphicBuffer> &bltBuf =
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer;
+ if (srcBuf->getWidth() != bltBuf->getWidth() ||
+ srcBuf->getHeight() != bltBuf->getHeight()) {
+ eglDestroyImageKHR(mBlitSlots[mNextBlitSlot].mEglDisplay,
+ image);
+ mBlitSlots[mNextBlitSlot].mEglImage = EGL_NO_IMAGE_KHR;
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer = NULL;
+ image = EGL_NO_IMAGE_KHR;
+ }
}
- image = createImage(dpy, mSlots[buf].mGraphicBuffer);
- mSlots[buf].mEglImage = image;
- mSlots[buf].mEglDisplay = dpy;
if (image == EGL_NO_IMAGE_KHR) {
- // NOTE: if dpy was invalid, createImage() is guaranteed to
- // fail. so we'd end up here.
- return -EINVAL;
+ sp<GraphicBuffer> &srcBuf = mSlots[buf].mGraphicBuffer;
+ status_t res = 0;
+
+ sp<GraphicBuffer> blitBuffer(
+ mGraphicBufferAlloc->createGraphicBuffer(
+ srcBuf->getWidth(), srcBuf->getHeight(),
+ PIXEL_FORMAT_RGBA_8888, srcBuf->getUsage(),
+ &res));
+ if (blitBuffer == 0) {
+ ST_LOGE("updateTexImage: SurfaceComposer::createGraphicBuffer failed");
+ return NO_MEMORY;
+ }
+ if (res != NO_ERROR) {
+ ST_LOGW("updateTexImage: SurfaceComposer::createGraphicBuffer error=%#04x", res);
+ }
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer = blitBuffer;
+
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ image = createImage(dpy, blitBuffer);
+ mBlitSlots[mNextBlitSlot].mEglImage = image;
+ mBlitSlots[mNextBlitSlot].mEglDisplay = dpy;
+ }
+
+ if (deferConversion) {
+ graphicBuffer = mSlots[buf].mGraphicBuffer;
+ mConversionSrcSlot = buf;
+ mConversionBltSlot = mNextBlitSlot;
+ // At this point graphicBuffer and image do not point
+ // at matching buffers. This is intentional as this
+ // surface might end up being taken care of by HWComposer,
+ // which needs access to the original buffer.
+ // GL however, is fed an EGLImage that is created from
+ // a conversion buffer. It will have its
+ // content updated once the surface is actually drawn
+ // in Layer::onDraw()
+ } else {
+ if (convert(mSlots[buf].mGraphicBuffer,
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer) != OK) {
+ LOGE("updateTexImage: convert failed");
+ return UNKNOWN_ERROR;
+ }
+ graphicBuffer = mBlitSlots[mNextBlitSlot].mGraphicBuffer;
+ }
+ // mBlitSlots contains several buffers (NUM_BLIT_BUFFER_SLOTS),
+ // advance (potentially wrap) the index
+ mNextBlitSlot = (mNextBlitSlot + 1) % NUM_BLIT_BUFFER_SLOTS;
+ } else {
+ mNeedsConversion = false;
+ image = mSlots[buf].mEglImage;
+ graphicBuffer = mSlots[buf].mGraphicBuffer;
+ if (image == EGL_NO_IMAGE_KHR) {
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ if (graphicBuffer == 0) {
+ ST_LOGE("buffer at slot %d is null", buf);
+ return BAD_VALUE;
+ }
+ image = createImage(dpy, graphicBuffer);
+ mSlots[buf].mEglImage = image;
+ mSlots[buf].mEglDisplay = dpy;
+ if (image == EGL_NO_IMAGE_KHR) {
+ // NOTE: if dpy was invalid, createImage() is guaranteed to
+ // fail. so we'd end up here.
+ return -EINVAL;
+ }
}
}
@@ -827,7 +929,7 @@ status_t SurfaceTexture::updateTexImage() {
// Update the SurfaceTexture state.
mCurrentTexture = buf;
- mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
+ mCurrentTextureBuf = graphicBuffer;
mCurrentCrop = mSlots[buf].mCrop;
mCurrentTransform = mSlots[buf].mTransform;
mCurrentScalingMode = mSlots[buf].mScalingMode;
@@ -853,8 +955,12 @@ bool SurfaceTexture::isExternalFormat(uint32_t format)
case HAL_PIXEL_FORMAT_YV12:
// Legacy/deprecated YUV formats
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_P:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_P:
return true;
}
@@ -996,6 +1102,14 @@ void SurfaceTexture::freeAllBuffersLocked() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
freeBufferLocked(i);
}
+ for (int i = 0; i < NUM_BLIT_BUFFER_SLOTS; i++) {
+ mBlitSlots[i].mGraphicBuffer = 0;
+ if (mBlitSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mBlitSlots[i].mEglDisplay, mBlitSlots[i].mEglImage);
+ mBlitSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+ mBlitSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+ }
+ }
}
void SurfaceTexture::freeAllBuffersExceptHeadLocked() {
@@ -1200,6 +1314,82 @@ void SurfaceTexture::dump(String8& result, const char* prefix,
}
}
+bool SurfaceTexture::conversionIsNeeded(const sp<GraphicBuffer>& graphicBuffer) {
+ int fmt = graphicBuffer->getPixelFormat();
+ return (fmt == PIXEL_FORMAT_YCBCR42XMBN) || (fmt == PIXEL_FORMAT_YCbCr_420_P);
+}
+
+status_t SurfaceTexture::convert() {
+ if (!mNeedsConversion)
+ return NO_ERROR;
+
+ if (mConversionBltSlot < 0 ||
+ mConversionBltSlot >= NUM_BLIT_BUFFER_SLOTS ||
+ mConversionSrcSlot < 0 ||
+ mConversionSrcSlot >= NUM_BUFFER_SLOTS) {
+ LOGE_IF(STE_DEFERDBG, "%s: Incorrect setup for deferred "
+ "texture conversion:\n"
+ "mConversionSrcSlot=%d mConversionBltSlot=%d", __FUNCTION__,
+ mConversionSrcSlot, mConversionBltSlot);
+ return BAD_VALUE;
+ }
+
+ if (mSlots[mConversionSrcSlot].mGraphicBuffer == NULL) {
+ LOGI_IF(STE_DEFERDBG, "%s: NULL source for deferred texture conversion.",
+ __FUNCTION__);
+ return OK;
+ }
+
+ if (mBlitSlots[mConversionBltSlot].mGraphicBuffer == NULL) {
+ LOGI_IF(STE_DEFERDBG, "%s: NULL destination for deferred "
+ "texture conversion.", __FUNCTION__);
+ return OK;
+ }
+
+ return convert(mSlots[mConversionSrcSlot].mGraphicBuffer,
+ mBlitSlots[mConversionBltSlot].mGraphicBuffer);
+}
+
+status_t SurfaceTexture::convert(sp<GraphicBuffer> &srcBuf, sp<GraphicBuffer> &dstBuf) {
+ copybit_image_t dstImg;
+ dstImg.w = dstBuf->getWidth();
+ dstImg.h = dstBuf->getHeight();
+ dstImg.format = dstBuf->getPixelFormat();
+ dstImg.handle = (native_handle_t*) dstBuf->getNativeBuffer()->handle;
+
+ copybit_image_t srcImg;
+ srcImg.w = srcBuf->getWidth();
+ srcImg.h = srcBuf->getHeight();
+ srcImg.format = srcBuf->getPixelFormat();
+ srcImg.base = NULL;
+ srcImg.handle = (native_handle_t*) srcBuf->getNativeBuffer()->handle;
+
+ copybit_rect_t dstCrop;
+ dstCrop.l = 0;
+ dstCrop.t = 0;
+ dstCrop.r = dstBuf->getWidth();
+ dstCrop.b = dstBuf->getHeight();
+
+ copybit_rect_t srcCrop;
+ srcCrop.l = 0;
+ srcCrop.t = 0;
+ srcCrop.r = srcBuf->getWidth();
+ srcCrop.b = srcBuf->getHeight();
+
+ region_iterator clip(Region(Rect(dstCrop.r, dstCrop.b)));
+ mBlitEngine->set_parameter(mBlitEngine, COPYBIT_TRANSFORM, 0);
+ mBlitEngine->set_parameter(mBlitEngine, COPYBIT_PLANE_ALPHA, 0xFF);
+ mBlitEngine->set_parameter(mBlitEngine, COPYBIT_DITHER, COPYBIT_ENABLE);
+
+ int err = mBlitEngine->stretch(
+ mBlitEngine, &dstImg, &srcImg, &dstCrop, &srcCrop, &clip);
+ if (err != 0) {
+ LOGE("\nError: Blit stretch operation failed (err:%d)\n", err);
+ return UNKNOWN_ERROR;
+ }
+ return OK;
+}
+
static void mtxMul(float out[16], const float a[16], const float b[16]) {
out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index fbabfc420cc5..90d401df1fac 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -40,6 +40,10 @@ include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
$(commonSources) \
EGLUtils.cpp \
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index ee186c84de9c..ec645dee621b 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -59,11 +59,21 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info)
// YUV format from the HAL are handled here
switch (format) {
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_P:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
info->bitsPerPixel = 16;
goto done;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_YCbCr_420_I:
+ case HAL_PIXEL_FORMAT_CbYCrY_420_I:
+ case HAL_PIXEL_FORMAT_YCBCR42XMBN:
info->bitsPerPixel = 12;
done:
info->format = format;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 8d71dcf644d0..b8ed9edb5bbf 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -808,7 +808,8 @@ public class MediaPlayer
}
/**
- * Sets the data source (file-path or http/rtsp URL) to use.
+ * Sets the data source (file-path or http/rtsp URL) to use. To select FM Radio as the data
+ * source, set the path to "fmradio://rx".
*
* @param path the path of the file, or the http/rtsp URL of the stream you want to play
* @throws IllegalStateException if it is called in an invalid state
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 08e603252c5c..c1f2f62c260b 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -168,6 +168,8 @@ public class MediaRecorder
* is applied.
*/
public static final int VOICE_COMMUNICATION = 7;
+ /** FM Radio Rx audio source */
+ public static final int FM_RADIO_RX = 8;
}
/**
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 7af4a8753576..190f8c3844da 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -2,6 +2,14 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
+ifeq ($(BOARD_HAVE_FMRADIO_SUPPORT),STERICSSON_FMRADIO_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_FMRADIO_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
AudioParameter.cpp
LOCAL_MODULE:= libmedia_helper
@@ -11,6 +19,14 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
+ifeq ($(BOARD_HAVE_FMRADIO_SUPPORT),STERICSSON_FMRADIO_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_FMRADIO_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
AudioTrack.cpp \
IAudioFlinger.cpp \
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 7b14c183b68e..4ec0483850b0 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -44,7 +44,6 @@ int AudioSystem::gPrevInFormat = AUDIO_FORMAT_PCM_16_BIT;
int AudioSystem::gPrevInChannelCount = 1;
size_t AudioSystem::gInBuffSize = 0;
-
// establish binder interface to AudioFlinger service
const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
{
@@ -626,11 +625,12 @@ audio_io_handle_t AudioSystem::getInput(int inputSource,
uint32_t format,
uint32_t channels,
audio_in_acoustics_t acoustics,
- int sessionId)
+ int sessionId,
+ audio_input_clients *inputClientId)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
- return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
+ return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId, inputClientId);
}
status_t AudioSystem::startInput(audio_io_handle_t input)
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index d58834b81684..1d1b72238acb 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -69,7 +69,8 @@ enum {
QUERY_EFFECT,
GET_EFFECT_DESCRIPTOR,
CREATE_EFFECT,
- MOVE_EFFECTS
+ MOVE_EFFECTS,
+ READ_INPUT
};
class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -432,7 +433,8 @@ public:
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
- uint32_t acoustics)
+ uint32_t acoustics,
+ uint32_t *pInputClientId)
{
Parcel data, reply;
uint32_t devices = pDevices ? *pDevices : 0;
@@ -446,6 +448,7 @@ public:
data.writeInt32(format);
data.writeInt32(channels);
data.writeInt32(acoustics);
+ data.writeIntPtr((intptr_t)pInputClientId);
remote()->transact(OPEN_INPUT, data, &reply);
int input = reply.readInt32();
devices = reply.readInt32();
@@ -459,11 +462,12 @@ public:
return input;
}
- virtual status_t closeInput(int input)
+ virtual status_t closeInput(int input, uint32_t *inputClientId)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(input);
+ data.writeIntPtr((intptr_t) inputClientId);
remote()->transact(CLOSE_INPUT, data, &reply);
return reply.readInt32();
}
@@ -516,6 +520,20 @@ public:
return reply.readInt32();
}
+ virtual size_t readInput(uint32_t *input, uint32_t inputClientId, void *buffer, uint32_t bytes, uint32_t *pOverwrittenBytes)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t) input);
+ data.writeInt32(inputClientId);
+ data.writeIntPtr((intptr_t) buffer);
+ data.writeInt32(bytes);
+ data.writeIntPtr((intptr_t) pOverwrittenBytes);
+ remote()->transact(READ_INPUT, data, &reply);
+
+ return reply.readInt32();
+ }
+
virtual int newAudioSessionId()
{
Parcel data, reply;
@@ -882,12 +900,14 @@ status_t BnAudioFlinger::onTransact(
uint32_t format = data.readInt32();
uint32_t channels = data.readInt32();
uint32_t acoutics = data.readInt32();
+ uint32_t *inputClientId = (uint32_t*) data.readIntPtr();
int input = openInput(&devices,
&samplingRate,
&format,
&channels,
- acoutics);
+ acoutics,
+ inputClientId);
reply->writeInt32(input);
reply->writeInt32(devices);
reply->writeInt32(samplingRate);
@@ -897,7 +917,9 @@ status_t BnAudioFlinger::onTransact(
} break;
case CLOSE_INPUT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(closeInput(data.readInt32()));
+ uint32_t input = data.readInt32();
+ uint32_t *inputClientId = (uint32_t*) data.readIntPtr();
+ reply->writeInt32(closeInput(input, inputClientId));
return NO_ERROR;
} break;
case SET_STREAM_OUTPUT: {
@@ -1010,6 +1032,16 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
return NO_ERROR;
} break;
+ case READ_INPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t* input = (uint32_t*) data.readIntPtr();
+ uint32_t inputClientId = data.readInt32();
+ void* buffer = (void*) data.readIntPtr();
+ uint32_t bytes = data.readInt32();
+ uint32_t *pOverwrittenBytes = (uint32_t*) data.readIntPtr();
+ reply->writeInt32(readInput(input, inputClientId, buffer, bytes, pOverwrittenBytes));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 50b4855a8e8d..7dc9e566e586 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -187,7 +187,8 @@ public:
uint32_t format,
uint32_t channels,
audio_in_acoustics_t acoustics,
- int audioSession)
+ int audioSession,
+ audio_input_clients *inputClientId)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -196,6 +197,7 @@ public:
data.writeInt32(static_cast <uint32_t>(format));
data.writeInt32(channels);
data.writeInt32(static_cast <uint32_t>(acoustics));
+ data.writeIntPtr((intptr_t)inputClientId);
data.writeInt32(audioSession);
remote()->transact(GET_INPUT, data, &reply);
return static_cast <audio_io_handle_t> (reply.readInt32());
@@ -478,13 +480,16 @@ status_t BnAudioPolicyService::onTransact(
uint32_t channels = data.readInt32();
audio_in_acoustics_t acoustics =
static_cast <audio_in_acoustics_t>(data.readInt32());
+ audio_input_clients *inputClientId =
+ (audio_input_clients*) data.readIntPtr();
int audioSession = data.readInt32();
audio_io_handle_t input = getInput(inputSource,
samplingRate,
format,
channels,
acoustics,
- audioSession);
+ audioSession,
+ inputClientId);
reply->writeInt32(static_cast <int>(input));
return NO_ERROR;
} break;
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index a3e2517b37d2..ec89f6fabe0d 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -6,6 +6,10 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
MediaRecorderClient.cpp \
MediaPlayerService.cpp \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 011c0b972583..736e7eed5b85 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1503,7 +1503,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper(
AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
size_t actualSize = (*me->mCallback)(
- me, buffer->raw, buffer->size, me->mCallbackCookie);
+ me, buffer->raw, buffer->size, me->mCallbackCookie);
if (actualSize == 0 && buffer->size > 0) {
// We've reached EOS but the audio track is not stopped yet,
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index b04fddb59a8b..fc46eab07c89 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -85,7 +85,6 @@ class MediaPlayerService : public BnMediaPlayerService
uint32_t sampleRate, int channelCount,
int format, int bufferCount,
AudioCallback cb, void *cookie);
-
virtual void start();
virtual ssize_t write(const void* buffer, size_t size);
virtual void stop();
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index e57878575b76..ff45d48a547e 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -6,6 +6,11 @@ include frameworks/base/media/libstagefright/codecs/common/Config.mk
ifeq ($(BOARD_HAVE_CODEC_SUPPORT),SAMSUNG_CODEC_SUPPORT)
LOCAL_CFLAGS += -DSAMSUNG_CODEC_SUPPORT
endif
+
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
ACodec.cpp \
AACExtractor.cpp \
@@ -40,6 +45,7 @@ LOCAL_SRC_FILES:= \
OMXClient.cpp \
OMXCodec.cpp \
OggExtractor.cpp \
+ PCMExtractor.cpp \
SampleIterator.cpp \
SampleTable.cpp \
StagefrightMediaScanner.cpp \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index bc45f83d3d96..1b4f79f89d69 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -40,6 +40,7 @@
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
+#include <media/stagefright/FMRadioDataSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractor.h>
@@ -1943,6 +1944,7 @@ status_t AwesomePlayer::prepareAsync_l() {
status_t AwesomePlayer::finishSetDataSource_l() {
sp<DataSource> dataSource;
+ char *mime = NULL;
bool isWidevineStreaming = false;
if (!strncasecmp("widevine://", mUri.string(), 11)) {
isWidevineStreaming = true;
@@ -2081,6 +2083,15 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return UNKNOWN_ERROR;
}
}
+ } else if (!strncasecmp("fmradio://rx", mUri.string(), 12)) {
+
+ mime = (char*) MEDIA_MIMETYPE_AUDIO_RAW;
+ // HACK: Removed the line below since it causes problems. Add it back if you want FM-Radio.
+ //dataSource = new FMRadioDataSource();
+ status_t err = dataSource->initCheck();
+ if (err != OK) {
+ return err;
+ }
} else {
dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
}
@@ -2107,8 +2118,7 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mWVMExtractor->setAdaptiveStreamingMode(true);
extractor = mWVMExtractor;
} else {
- extractor = MediaExtractor::Create(
- dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
+ extractor = MediaExtractor::Create(dataSource, mime);
if (extractor == NULL) {
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 57989c5e4a4a..11502ebf2994 100755..100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -111,6 +111,10 @@ static int32_t getColorFormat(const char* colorFormat) {
return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
}
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420MB)) {
+ return OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB;
+ }
+
LOGE("Uknown color format (%s), please add it to "
"CameraSource::getColorFormat", colorFormat);
@@ -535,13 +539,16 @@ status_t CameraSource::initWithCameraAccess(
// XXX: query camera for the stride and slice height
// when the capability becomes available.
+ int stride = newCameraParams.getInt(CameraParameters::KEY_RECORD_STRIDE);
+ int sliceHeight = newCameraParams.getInt(CameraParameters::KEY_RECORD_SLICE_HEIGHT);
+
mMeta = new MetaData;
mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
mMeta->setInt32(kKeyColorFormat, mColorFormat);
mMeta->setInt32(kKeyWidth, mVideoSize.width);
mMeta->setInt32(kKeyHeight, mVideoSize.height);
- mMeta->setInt32(kKeyStride, mVideoSize.width);
- mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
+ mMeta->setInt32(kKeyStride, stride != -1 ? stride : mVideoSize.width);
+ mMeta->setInt32(kKeySliceHeight, sliceHeight != -1 ? sliceHeight : mVideoSize.height);
mMeta->setInt32(kKeyFrameRate, mVideoFrameRate);
return OK;
}
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 43539bb8d2ac..8f8257136b6d 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -20,6 +20,7 @@
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
#include "include/MPEG2PSExtractor.h"
+#include "include/PCMExtractor.h"
#include "include/MPEG2TSExtractor.h"
#include "include/NuCachedSource2.h"
#include "include/HTTPBase.h"
@@ -32,6 +33,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
+#include <media/stagefright/FMRadioDataSource.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/String8.h>
diff --git a/media/libstagefright/FMRadioDataSource.cpp b/media/libstagefright/FMRadioDataSource.cpp
new file mode 100644
index 000000000000..09780f26e6e8
--- /dev/null
+++ b/media/libstagefright/FMRadioDataSource.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andreas Gustafsson (andreas.a.gustafsson@stericsson.com)
+ * for ST-Ericsson
+ */
+
+#define LOG_TAG "FMRadioDataSource"
+#include <utils/Log.h>
+
+#include <media/stagefright/FMRadioDataSource.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/AudioSystem.h>
+#include <media/IAudioPolicyService.h>
+#include <binder/IServiceManager.h>
+#include <media/AudioSystem.h>
+#include <media/mediarecorder.h>
+#include <media/IAudioFlinger.h>
+#include <system/audio.h>
+
+
+namespace android {
+
+FMRadioDataSource::FMRadioDataSource() {
+
+ mFormat = android_audio_legacy::AudioSystem::PCM_16_BIT;
+ mChannels = android_audio_legacy::AudioSystem::CHANNEL_IN_STEREO;
+ mSampleRate = 48000;
+ mFlags = 0;
+ mOverwrittenBytes = 0;
+ mInputClientId = AUDIO_INPUT_CLIENT_PLAYBACK;
+ int inputSource = AUDIO_SOURCE_FM_RADIO_RX;
+
+ mStream = (android_audio_legacy::AudioStreamIn*) AudioSystem::getInput(inputSource,mSampleRate, mFormat, mChannels,
+ (audio_in_acoustics_t)mFlags,0,&mInputClientId);
+ if (mStream != NULL) {
+ AudioSystem::startInput((audio_io_handle_t) mStream);
+ }
+}
+
+FMRadioDataSource::~FMRadioDataSource() {
+
+ if (mStream != NULL) {
+ AudioSystem::stopInput((audio_io_handle_t) mStream);
+ AudioSystem::releaseInput((audio_io_handle_t) mStream);
+ }
+}
+
+status_t FMRadioDataSource::initCheck() const {
+ return mStream != NULL ? OK : NO_INIT;
+}
+
+ssize_t FMRadioDataSource::readAt(off64_t offset, void *data, size_t size) {
+ if(mStream != NULL) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ return af->readInput((uint32_t*)mStream, mInputClientId, data, size, &mOverwrittenBytes);
+ }
+ return 0;
+}
+
+status_t FMRadioDataSource::getSize(off64_t *size) {
+ *size = 0;
+ return OK;
+}
+
+uint32_t FMRadioDataSource::getBufferSize() {
+ return mStream->bufferSize();
+}
+
+uint32_t FMRadioDataSource::getNumChannels() {
+ return android_audio_legacy::AudioSystem::popCount(mChannels);
+}
+
+uint32_t FMRadioDataSource::getSampleRate() {
+ return mSampleRate;
+}
+
+uint32_t FMRadioDataSource::getFormat() {
+ if (mFormat == android_audio_legacy::AudioSystem::PCM_16_BIT) {
+ return 16;
+ } else if (mFormat == android_audio_legacy::AudioSystem::PCM_8_BIT) {
+ return 8;
+ }
+ return 0;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 46d87df66889..46d87df66889 100755..100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 444e823295a3..43e305c8c62f 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -24,8 +24,10 @@ const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8";
const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
const char *MEDIA_MIMETYPE_VIDEO_H263 = "video/3gpp";
+const char *MEDIA_MIMETYPE_VIDEO_H263_SW = "video/3gpp-sw";
const char *MEDIA_MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
const char *MEDIA_MIMETYPE_VIDEO_RAW = "video/raw";
+const char *MEDIA_MIMETYPE_VIDEO_VC1 = "video/vc1";
const char *MEDIA_MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
const char *MEDIA_MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 374ecf703613..93fe491e2083 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -24,6 +24,7 @@
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
#include "include/MPEG2PSExtractor.h"
+#include "include/PCMExtractor.h"
#include "include/MPEG2TSExtractor.h"
#include "include/DRMExtractor.h"
#include "include/WVMExtractor.h"
@@ -115,6 +116,8 @@ sp<MediaExtractor> MediaExtractor::Create(
ret = new AACExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
ret = new MPEG2PSExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ ret = new PCMExtractor(source);
}
if (ret != NULL) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index c080b6c31f2a..33e85a9a06ff 100755..100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -117,6 +117,7 @@ static sp<MediaSource> InstantiateSoftwareEncoder(
static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.ST.mp3.decoder" },
// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
{ MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" },
{ MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, "OMX.Nvidia.mp2.decoder" },
@@ -126,11 +127,13 @@ static const CodecInfo kDecoderInfo[] = {
// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" },
+ { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.ST.aac.decoder" },
// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.ST.VFM.MPEG4Dec" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
@@ -138,12 +141,15 @@ static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.ST.VFM.MPEG4Dec" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
+ { MEDIA_MIMETYPE_VIDEO_H263_SW, "OMX.ST.VFM.MPEG4HostDec" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.ST.VFM.H264Dec" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
@@ -155,6 +161,7 @@ static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" },
{ MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG2, "OMX.Nvidia.mpeg2v.decode" },
+ { MEDIA_MIMETYPE_VIDEO_VC1, "OMX.ST.VFM.VC1Dec" },
};
static const CodecInfo kEncoderInfo[] = {
@@ -164,6 +171,7 @@ static const CodecInfo kEncoderInfo[] = {
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.ST.VFM.MPEG4Enc" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
@@ -171,6 +179,7 @@ static const CodecInfo kEncoderInfo[] = {
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.encoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.ST.VFM.MPEG4Enc" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
@@ -178,6 +187,7 @@ static const CodecInfo kEncoderInfo[] = {
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.encoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.ST.VFM.H264Enc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.H264E" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
@@ -292,6 +302,18 @@ static int CompareSoftwareCodecsFirst(
return 0;
}
+static uint32_t OmxToHALFormat(OMX_COLOR_FORMATTYPE omxValue) {
+ switch (omxValue) {
+ case OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB:
+ return HAL_PIXEL_FORMAT_YCBCR42XMBN;
+ case OMX_COLOR_FormatYUV420Planar:
+ return HAL_PIXEL_FORMAT_YCbCr_420_P;
+ default:
+ LOGI("Unknown OMX pixel format (0x%X), passing it on unchanged", omxValue);
+ return omxValue;
+ }
+}
+
// static
uint32_t OMXCodec::getComponentQuirks(
const char *componentName, bool isEncoder) {
@@ -376,6 +398,17 @@ uint32_t OMXCodec::getComponentQuirks(
quirks |= kOutputBuffersAreUnreadable;
}
+ if (!isEncoder && !strncmp(componentName, "OMX.ST.VFM.", 11)) {
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ }
+
+ if (!strncmp(componentName, "OMX.ST.VFM.MPEG4Enc", 19) ||
+ !strncmp(componentName, "OMX.ST.VFM.H264Enc", 18)) {
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ quirks |= kRequiresStoreMetaDataBeforeIdle;
+ }
+
return quirks;
}
@@ -901,6 +934,7 @@ static size_t getFrameSize(
case OMX_COLOR_FormatYUV420Planar:
case OMX_COLOR_FormatYUV420SemiPlanar:
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB:
/*
* FIXME: For the Opaque color format, the frame size does not
* need to be (w*h*3)/2. It just needs to
@@ -1432,7 +1466,7 @@ status_t OMXCodec::setVideoOutputFormat(
|| format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
|| format.eColorFormat == OMX_COLOR_FormatCbYCrY
|| format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
+ || format.eColorFormat == OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB
#ifdef SAMSUNG_CODEC_SUPPORT
|| format.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress
|| format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled
@@ -1590,6 +1624,8 @@ void OMXCodec::setComponentRole(
"video_decoder.mpeg4", "video_encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_H263,
"video_decoder.h263", "video_encoder.h263" },
+ { MEDIA_MIMETYPE_VIDEO_VC1,
+ "video_decoder.vc1", "video_encoder.vc1" },
};
static const size_t kNumMimeToRole =
@@ -1659,6 +1695,15 @@ status_t OMXCodec::init() {
CHECK_EQ((int)mState, (int)LOADED);
status_t err;
+ if ((mQuirks & kRequiresStoreMetaDataBeforeIdle)
+ && (mFlags & kStoreMetaDataInVideoBuffers)) {
+ err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
+ if (err != OK) {
+ LOGE("Storing meta data in video buffers is not supported");
+ return err;
+ }
+ }
+
if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
CHECK_EQ(err, (status_t)OK);
@@ -1714,7 +1759,8 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
}
status_t err = OK;
- if ((mFlags & kStoreMetaDataInVideoBuffers)
+ if (!(mQuirks & kRequiresStoreMetaDataBeforeIdle)
+ && (mFlags & kStoreMetaDataInVideoBuffers)
&& portIndex == kPortIndexInput) {
err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
if (err != OK) {
@@ -1891,8 +1937,8 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
mNativeWindow.get(),
def.format.video.nFrameWidth,
def.format.video.nFrameHeight,
- def.format.video.eColorFormat);
-#else
+ OmxToHALFormat(def.format.video.eColorFormat));
+#else /* SAMSUNG_CODEC_SUPPORT */
OMX_COLOR_FORMATTYPE eColorFormat;
switch (def.format.video.eColorFormat) {
@@ -4272,6 +4318,7 @@ static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
"OMX_VIDEO_CodingRV",
"OMX_VIDEO_CodingAVC",
"OMX_VIDEO_CodingMJPEG",
+ "OMX_VIDEO_CodingVC1",
};
size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
diff --git a/media/libstagefright/PCMExtractor.cpp b/media/libstagefright/PCMExtractor.cpp
new file mode 100644
index 000000000000..d85af33e63f7
--- /dev/null
+++ b/media/libstagefright/PCMExtractor.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andreas Gustafsson (andreas.a.gustafsson@stericsson.com)
+ * for ST-Ericsson
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PCMExtractor"
+#include <utils/Log.h>
+
+#include "include/PCMExtractor.h"
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+namespace android {
+
+static const uint16_t kDefaultNumChannels = 2;
+static const uint32_t kDefaultSampleRate = 48000;
+static const uint16_t kDefaultFormat = 16;
+
+struct PCMSource : public MediaSource {
+ PCMSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &meta,
+ int32_t bitsPerSample,
+ off_t offset, size_t size);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~PCMSource();
+
+private:
+ static const size_t kMaxFrameSize;
+
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ int32_t mSampleRate;
+ int32_t mNumChannels;
+ int32_t mBitsPerSample;
+ off_t mOffset;
+ size_t mSize;
+ bool mStarted;
+ MediaBufferGroup *mGroup;
+ off_t mCurrentPos;
+ uint32_t mBufferSize;
+
+ PCMSource(const PCMSource &);
+ PCMSource &operator=(const PCMSource &);
+};
+
+PCMExtractor::PCMExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mValidFormat(false) {
+ mInitCheck = init();
+}
+
+PCMExtractor::~PCMExtractor() {
+}
+
+sp<MetaData> PCMExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck != OK) {
+ return meta;
+ }
+
+ meta->setCString(kKeyMIMEType, "audio/raw");
+
+ return meta;
+}
+
+size_t PCMExtractor::countTracks() {
+ return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> PCMExtractor::getTrack(size_t index) {
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+
+ return new PCMSource(
+ mDataSource, mTrackMeta,
+ mBitsPerSample, mDataOffset, mDataSize);
+}
+
+sp<MetaData> PCMExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+
+ return mTrackMeta;
+}
+
+status_t PCMExtractor::init() {
+ mNumChannels = kDefaultNumChannels;
+ mSampleRate = kDefaultSampleRate;
+ mBitsPerSample = kDefaultFormat;
+ mDataOffset = 0;
+ mDataSize = 0;
+ mValidFormat = true;
+ mTrackMeta = new MetaData;mTrackMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
+ mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
+ return OK;
+}
+
+const size_t PCMSource::kMaxFrameSize = 4800;
+
+PCMSource::PCMSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &meta,
+ int32_t bitsPerSample,
+ off_t offset, size_t size)
+ : mDataSource(dataSource),
+ mMeta(meta),
+ mSampleRate(0),
+ mNumChannels(0),
+ mBitsPerSample(bitsPerSample),
+ mOffset(offset),
+ mSize(size),
+ mStarted(false),
+ mGroup(NULL),
+ mBufferSize(0) {
+ CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
+ CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
+}
+
+PCMSource::~PCMSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t PCMSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ mBufferSize = kMaxFrameSize;
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+ if (mBitsPerSample == 8) {
+ // As a temporary buffer for 8->16 bit conversion.
+ mGroup->add_buffer(new MediaBuffer(mBufferSize));
+ }
+
+ mCurrentPos = mOffset;
+
+ mStarted = true;
+ return OK;
+}
+
+status_t PCMSource::stop() {
+
+ CHECK(mStarted);
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+ return OK;
+}
+
+sp<MetaData> PCMSource::getFormat() {
+ return mMeta;
+}
+
+status_t PCMSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seek = ReadOptions::SEEK_CLOSEST_SYNC;
+ if (options != NULL && options->getSeekTo(&seekTimeUs,&seek)) {
+ int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * 2;
+ if (pos > mSize) {
+ pos = mSize;
+ }
+ mCurrentPos = pos + mOffset;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ ssize_t n = mDataSource->readAt(
+ mCurrentPos, buffer->data(), mBufferSize);
+ if (n <= 0) {
+ buffer->release();
+ buffer = NULL;
+ return ERROR_END_OF_STREAM;
+ }
+
+ mCurrentPos += n;
+
+ buffer->set_range(0, n);
+
+ if (mBitsPerSample == 8) {
+ // Convert 8-bit unsigned samples to 16-bit signed.
+
+ MediaBuffer *tmp;
+ CHECK_EQ(mGroup->acquire_buffer(&tmp), OK);
+
+ // The new buffer holds the sample number of samples, but each
+ // one is 2 bytes wide.
+ tmp->set_range(0, 2 * n);
+
+ int16_t *dst = (int16_t *)tmp->data();
+ const uint8_t *src = (const uint8_t *)buffer->data();
+ while (n-- > 0) {
+ *dst++ = ((int16_t)(*src) - 128) * 256;
+ ++src;
+ }
+
+ buffer->release();
+ buffer = tmp;
+ } else if (mBitsPerSample == 24) {
+ // Convert 24-bit signed samples to 16-bit signed.
+
+ const uint8_t *src =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+ int16_t *dst = (int16_t *)src;
+
+ size_t numSamples = buffer->range_length() / 3;
+ for (size_t i = 0; i < numSamples; ++i) {
+ int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
+ x = (x << 8) >> 8; // sign extension
+
+ x = x >> 8;
+ *dst++ = (int16_t)x;
+ src += 3;
+ }
+
+ buffer->set_range(buffer->range_offset(), 2 * numSamples);
+ }
+
+ size_t bytesPerSample = mBitsPerSample >> 3;
+
+ buffer->meta_data()->setInt64(
+ kKeyTime,
+ 1000000LL * (mCurrentPos - mOffset)
+ / (mNumChannels * bytesPerSample) / mSampleRate);
+
+
+ *out = buffer;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index 62ba40f449bc..89ed50f2b454 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -1,6 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
ColorConverter.cpp \
SoftwareRenderer.cpp
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 5cc3f78804ab..70ef74eba1c7 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -47,6 +47,7 @@ bool ColorConverter::isValid() const {
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
case OMX_COLOR_FormatYUV420SemiPlanar:
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB:
return true;
default:
@@ -122,6 +123,10 @@ status_t ColorConverter::convert(
err = convertTIYUV420PackedSemiPlanar(src, dst);
break;
+ case OMX_STE_COLOR_FormatYUV420PackedSemiPlanarMB:
+ err = convertSTEYUV420PackedSemiPlanarMB(src, dst);
+ break;
+
default:
{
CHECK(!"Should not be here. Unknown color conversion.");
@@ -493,6 +498,143 @@ status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
return OK;
}
+status_t ColorConverter::convertSTEYUV420PackedSemiPlanarMB(
+ const BitmapParams &src, const BitmapParams &dst) {
+
+ if (!((dst.mWidth & 1) == 0
+ && src.mCropLeft == 0
+ && src.mCropTop == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ OMX_U32 mx = src.mWidth / 16;
+ OMX_U32 my = src.mHeight / 16;
+ OMX_U32 lx, ly;
+ OMX_U32 *pChroma, *pLuma = (OMX_U32 *)src.mBits;
+
+ pChroma = (OMX_U32 *)src.mBits + mx * my * 64;
+ for (ly = 0; ly < my; ly++) {
+ for (lx = 0; lx < mx; lx++) {
+ OMX_U32 col, row, lumaWord, chromaWord1 = 0, rgbWord, i;
+ OMX_U8 y[4], cb[4], cr[4], r[4], g[4], b[4];
+ OMX_U32 *dstBuf, *locBuf;
+ OMX_U32 *pBurstLuma = 0, *pBurstChroma = 0;
+ OMX_U32 *pWordLuma = 0, *pWordChroma = 0;
+ OMX_U8 nbOfBlock;
+
+ dstBuf = ((OMX_U32 *)dst.mBits) + (ly * 16) * dst.mWidth / 2;
+ dstBuf += (lx * 16) / 2;
+
+ pBurstLuma = pLuma;
+ pBurstChroma = pChroma;
+
+ for (col = 0; col < 2; col++) {
+ // conversion of a macroblock
+ for (nbOfBlock = 0; nbOfBlock < 2; nbOfBlock++) {
+ locBuf = dstBuf + 4 * col + 2 * nbOfBlock;
+ OMX_U32 dstRowOrigo = ly * 16 * dst.mWidth;
+
+ switch (nbOfBlock) {
+ case 0:
+ pWordLuma = pBurstLuma;
+ pWordChroma = pBurstChroma;
+ break;
+ case 1:
+ pWordLuma = pBurstLuma + 1;
+ pWordChroma = pBurstChroma + 1;
+ break;
+ }
+ for (row = 0; row < 16; row++) {
+
+ // Check for cropping on the y axis
+ if (ly * 16 + row >= dst.mHeight) {
+ break;
+ }
+
+ lumaWord = *pWordLuma;
+ pWordLuma += 2;
+ if (row % 2 == 0) {
+ chromaWord1 = *pWordChroma;
+ pWordChroma += 2;
+ }
+
+ y[3] = ((lumaWord >> 24) & 0xff);
+ y[2] = ((lumaWord >> 16) & 0xff);
+ y[1] = ((lumaWord >> 8) & 0xff);
+ y[0] = ((lumaWord >> 0) & 0xff);
+
+ cb[0] = cb[1] = ((chromaWord1 >> 0) & 0xff);
+ cb[2] = cb[3] = ((chromaWord1 >> 16) & 0xff);
+ cr[0] = cr[1] = ((chromaWord1 >> 8) & 0xff);
+ cr[2] = cr[3] = ((chromaWord1 >> 24) & 0xff);
+
+ for (i = 0; i < 4; i++) {
+
+ int32_t rW,gW,bW;
+
+ rW = 298 * y[i] + 408 * cr[i] - 57059;
+ gW = 298 * y[i] - 100 * cb[i] - 208 * cr[i] + 34713;
+ bW = 298 * y[i] + 516 * cb[i] - 70887;
+
+ if (rW < 0) {
+ r[i] = 0;
+ } else if (rW >= 65536) {
+ r[i] = 255;
+ } else {
+ r[i] = (rW >> 8);
+ }
+ if (gW < 0) {
+ g[i] = 0;
+ } else if (gW >= 65536) {
+ g[i] = 255;
+ } else {
+ g[i] = (gW >> 8);
+ }
+ if (bW < 0) {
+ b[i] = 0;
+ } else if (bW >= 65536) {
+ b[i] = 255;
+ } else {
+ b[i] = (bW >> 8);
+ }
+ r[i] >>= 3;
+ g[i] >>= 2;
+ b[i] >>= 3;
+ }
+ for (i = 0; i < 4; i += 2) {
+
+ // Check for cropping on the x axis
+ OMX_U32 rowPos = (locBuf - (OMX_U32 *)dst.mBits) * 2 - dstRowOrigo;
+ if (rowPos >= dst.mWidth) {
+ locBuf++;
+ continue;
+ }
+
+ rgbWord = (r[i + 1] << 27) +
+ (g[i + 1] << 21) +
+ (b[i + 1] << 16) +
+ (r[i] << 11) +
+ (g[i] << 5) +
+ (b[i] << 0);
+ *locBuf++ = rgbWord;
+ }
+ locBuf += dst.mWidth / 2 - 2;
+ dstRowOrigo += dst.mWidth;
+ } //end of for 16 loop
+ } //end of 2 block loop
+ pBurstLuma += 32;
+ pBurstChroma += 16;
+ } // end of 2 col loop
+ pLuma += 64;
+ pChroma += 32;
+ }
+ }
+
+ return OK;
+}
+
uint8_t *ColorConverter::initClip() {
static const signed kClipMin = -278;
static const signed kClipMax = 535;
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
index 5499c32bbaba..5d317862cc1f 100644
--- a/media/libstagefright/foundation/ABitReader.cpp
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -22,7 +22,9 @@ namespace android {
ABitReader::ABitReader(const uint8_t *data, size_t size)
: mData(data),
+ mOriginalData(data),
mSize(size),
+ mOriginalSize(size),
mReservoir(0),
mNumBitsLeft(0) {
}
@@ -78,6 +80,19 @@ void ABitReader::skipBits(size_t n) {
}
}
+void ABitReader::rewindBits(size_t n) {
+ CHECK_GE(mOriginalSize * 8 - numBitsLeft(), n);
+
+ size_t bitsLeft = numBitsLeft();
+
+ mData = mOriginalData;
+ mSize = mOriginalSize;
+ mReservoir = 0;
+ mNumBitsLeft = 0;
+
+ skipBits(mOriginalSize * 8 - bitsLeft - n);
+}
+
void ABitReader::putBits(uint32_t x, size_t n) {
CHECK_LE(n, 32u);
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index d5025a13ed86..648f945334c7 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -1,6 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
AAtomizer.cpp \
ABitReader.cpp \
diff --git a/media/libstagefright/include/PCMExtractor.h b/media/libstagefright/include/PCMExtractor.h
new file mode 100644
index 000000000000..eec72326283e
--- /dev/null
+++ b/media/libstagefright/include/PCMExtractor.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andreas Gustafsson (andreas.a.gustafsson@stericsson.com)
+ * for ST-Ericsson
+ */
+
+#ifndef PCM_EXTRACTOR_H_
+
+#define PCM_EXTRACTOR_H_
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaExtractor.h>
+
+using namespace android;
+
+namespace android {
+
+class DataSource;
+class String8;
+
+class PCMExtractor : public MediaExtractor {
+public:
+ // Extractor assumes ownership of "source".
+ PCMExtractor(const sp<DataSource> &source);
+
+ virtual size_t countTracks();
+ virtual sp<MediaSource> getTrack(size_t index);
+ virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+
+ virtual sp<MetaData> getMetaData();
+
+protected:
+ virtual ~PCMExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+ bool mValidFormat;
+ uint16_t mNumChannels;
+ uint32_t mSampleRate;
+ uint16_t mBitsPerSample;
+ off_t mDataOffset;
+ size_t mDataSize;
+ sp<MetaData> mTrackMeta;
+
+ status_t init();
+
+ PCMExtractor(const PCMExtractor &);
+ PCMExtractor &operator=(const PCMExtractor &);
+};
+
+} // namespace android
+
+#endif // PCM_EXTRACTOR_H_
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index d844f3dfe6b6..0452a4d8bdaf 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -1,6 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
LOCAL_SRC_FILES:= \
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index 1e33f05f0ce1..edc21693af7d 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -34,6 +34,7 @@ static const struct {
const char *mRole;
} kComponents[] = {
+ { "OMX.ST.aac.decoder", "ste_aacdec", "audio_decoder.aac" },
{ "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },
{ "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },
{ "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" },
@@ -42,6 +43,7 @@ static const struct {
{ "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" },
{ "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },
{ "OMX.google.mpeg4.decoder", "mpeg4dec", "video_decoder.mpeg4" },
+ { "OMX.ST.mp3.decoder", "ste_mp3dec", "audio_decoder.mp3" },
{ "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
{ "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },
{ "OMX.google.vpx.decoder", "vpxdec", "video_decoder.vpx" },
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index 11d9c220959c..43751a3550fc 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -201,13 +201,33 @@ static status_t parseAudioSpecificConfig(ABitReader *bits, sp<ABuffer> *asc) {
CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType),
(status_t)OK);
- sbrPresent = bits->getBits(1);
-
- if (sbrPresent == 1) {
- unsigned extensionSamplingFreqIndex = bits->getBits(4);
- if (extensionSamplingFreqIndex == 0x0f) {
- /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+ if (extensionAudioObjectType == 5) {
+ sbrPresent = bits->getBits(1);
+ if (sbrPresent == 1) {
+ unsigned extensionSamplingFreqIndex = bits->getBits(4);
+ if (extensionSamplingFreqIndex == 0x0f) {
+ /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+ }
+ if (bits->numBitsLeft() >= 12) {
+ syncExtensionType = bits->getBits(11);
+ if (syncExtensionType == 0x548) {
+ /* unsigned psPresent */bits->getBits(1);
+ } else {
+ // Rewind bitstream so that the reading of second
+ // syncExtensionType has no effect
+ bits->rewindBits(11);
+ }
+ }
+ }
+ } else if (extensionAudioObjectType == 22) {
+ sbrPresent = bits->getBits(1);
+ if (sbrPresent == 1) {
+ unsigned extensionSamplingFreqIndex = bits->getBits(4);
+ if (extensionSamplingFreqIndex == 0x0f) {
+ /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+ }
}
+ /* unsigned extensionChannelConfiguration = */bits->getBits(4);
}
size_t numBitsInExtension =
@@ -223,7 +243,7 @@ static status_t parseAudioSpecificConfig(ABitReader *bits, sp<ABuffer> *asc) {
bits->skipBits(8 - (numBitsInExtension & 7));
}
} else {
- bits->putBits(syncExtensionType, 11);
+ bits->rewindBits(11);
}
}
@@ -335,11 +355,14 @@ static status_t parseStreamMuxConfig(
break;
}
+ status_t parseResult = OK;
*otherDataPresent = bits->getBits(1);
*otherDataLenBits = 0;
if (*otherDataPresent) {
if (audioMuxVersion == 1) {
TRESPASS(); // XXX to be implemented
+ } else if (bits->numBitsLeft() < 9) {
+ parseResult = ERROR_MALFORMED;
} else {
*otherDataLenBits = 0;
@@ -349,13 +372,45 @@ static status_t parseStreamMuxConfig(
otherDataLenEsc = bits->getBits(1);
unsigned otherDataLenTmp = bits->getBits(8);
(*otherDataLenBits) += otherDataLenTmp;
- } while (otherDataLenEsc);
+ } while (otherDataLenEsc && bits->numBitsLeft() >= 9);
+
+ if (otherDataLenEsc) {
+ parseResult = ERROR_MALFORMED;
+ }
+ }
+ }
+
+ if (parseResult == OK && bits->numBitsLeft() >= 1) {
+ unsigned crcCheckPresent = bits->getBits(1);
+ if (crcCheckPresent && bits->numBitsLeft() >= 8) {
+ /* unsigned crcCheckSum = */bits->getBits(8);
+ } else if (crcCheckPresent && bits->numBitsLeft() < 8) {
+ parseResult = ERROR_MALFORMED;
+ }
+ } else {
+ parseResult = ERROR_MALFORMED;
+ }
+
+ // Verify that only bits are left for byte aligning and that
+ // any remaining bits are 0
+ if (bits->numBitsLeft() / 8 > 0) {
+ parseResult = ERROR_MALFORMED;
+ } else {
+ unsigned remainder = bits->getBits(bits->numBitsLeft());
+ if (remainder != 0) {
+ parseResult = ERROR_MALFORMED;
}
}
- unsigned crcCheckPresent = bits->getBits(1);
- if (crcCheckPresent) {
- /* unsigned crcCheckSum = */bits->getBits(8);
+ // Check if config string parsing has failed (then probably due to a
+ // malformed AudioSpecificConfig) and if so, assume most common
+ // configuration for the variables after AudioSpecificConfig.
+ if (parseResult != OK) {
+ LOGW("LATM config string parsing has failed, assuming most common case "
+ "of frameLengthType=0, otherDataPresent=0, and otherDataLenBits=0");
+ *frameLengthType = 0;
+ *otherDataPresent = 0;
+ *otherDataLenBits = 0;
}
return OK;
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index 823034787fbb..d97a8bf84465 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -2,6 +2,10 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
AAMRAssembler.cpp \
AAVCAssembler.cpp \
@@ -35,6 +39,10 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
rtp_test.cpp
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index ca1186337829..142fa0513612 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -236,18 +236,6 @@ struct ANativeWindowBuffer;
/* EGL_NV_system_time
*/
-#ifndef EGL_NV_system_time
-#define EGL_NV_system_time 1
-typedef khronos_int64_t EGLint64NV;
-typedef khronos_uint64_t EGLuint64NV;
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
-#endif
-typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void);
-typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
-#endif
-
/* EGL_ANDROID_blob_cache
*/
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index 9db4e252c559..28c7aef71288 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -188,6 +188,18 @@ typedef void* GLeglImageOES;
#endif
/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
* EXT extension tokens
*------------------------------------------------------------------------*/
@@ -603,6 +615,20 @@ typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monito
#endif
/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
* EXT extension functions
*------------------------------------------------------------------------*/
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index e5004e1e5033..84949bb5ab57 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -49,27 +49,23 @@ using namespace android;
// ----------------------------------------------------------------------------
-#define EGL_VERSION_HW_ANDROID 0x3143
-
-#ifdef TARGET_BOARD_SNOWBALL
static char const * const sVendorString = "Android";
static char const * const sVersionString = "1.4 Android META-EGL";
static char const * const sClientApiString = "OpenGL ES";
static char const * const sExtensionString =
- "EGL_KHR_image "
- "EGL_KHR_image_base "
- "EGL_KHR_image_pixmap "
- "EGL_KHR_gl_texture_2D_image "
- "EGL_KHR_gl_texture_cubemap_image "
- "EGL_KHR_gl_renderbuffer_image "
- "EGL_KHR_fence_sync "
- "EGL_ANDROID_image_native_buffer "
- "EGL_ANDROID_swap_rectangle "
-#ifndef TARGET_BOARD_SNOWBALL
- "EGL_NV_system_time "
-#endif
- ;
-#endif
+ "EGL_KHR_image "
+ "EGL_KHR_image_base "
+ "EGL_KHR_image_pixmap "
+ "EGL_KHR_gl_texture_2D_image "
+ "EGL_KHR_gl_texture_cubemap_image "
+ "EGL_KHR_gl_renderbuffer_image "
+ "EGL_KHR_fence_sync "
+ "EGL_ANDROID_image_native_buffer "
+ "EGL_ANDROID_swap_rectangle "
+ /* "EGL_NV_system_time "*/
+ ;
+
+#define EGL_VERSION_HW_ANDROID 0x3143
struct extention_map_t {
const char* name;
@@ -85,12 +81,6 @@ static const extention_map_t sExtentionMap[] = {
(__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
{ "eglDestroyImageKHR",
(__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
-#ifndef TARGET_BOARD_SNOWBALL
- { "eglGetSystemTimeFrequencyNV",
- (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
- { "eglGetSystemTimeNV",
- (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
-#endif
};
// accesses protected by sExtensionMapMutex
@@ -993,13 +983,10 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name)
case EGL_VERSION:
return dp->getVersionString();
case EGL_EXTENSIONS:
-#ifdef TARGET_BOARD_SNOWBALL
if (NULL != dp->disp[IMPL_HARDWARE].queryString.extensions)
return dp->disp[IMPL_HARDWARE].queryString.extensions;
else
return sExtensionString;
-#endif
- return dp->getExtensionString();
case EGL_CLIENT_APIS:
return dp->getClientApiString();
case EGL_VERSION_HW_ANDROID: {
@@ -1472,47 +1459,3 @@ EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute
/* ANDROID extensions entry-point go here */
-#ifndef TARGET_BOARD_SNOWBALL
-// ----------------------------------------------------------------------------
-// NVIDIA extensions
-// ----------------------------------------------------------------------------
-EGLuint64NV eglGetSystemTimeFrequencyNV()
-{
- clearError();
-
- if (egl_init_drivers() == EGL_FALSE) {
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- }
-
- EGLuint64NV ret = 0;
- egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
-
- if (cnx->dso) {
- if (cnx->egl.eglGetSystemTimeFrequencyNV) {
- return cnx->egl.eglGetSystemTimeFrequencyNV();
- }
- }
-
- return setErrorQuiet(EGL_BAD_DISPLAY, 0);
-}
-
-EGLuint64NV eglGetSystemTimeNV()
-{
- clearError();
-
- if (egl_init_drivers() == EGL_FALSE) {
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- }
-
- EGLuint64NV ret = 0;
- egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
-
- if (cnx->dso) {
- if (cnx->egl.eglGetSystemTimeNV) {
- return cnx->egl.eglGetSystemTimeNV();
- }
- }
-
- return setErrorQuiet(EGL_BAD_DISPLAY, 0);
-}
-#endif
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 9ebdecf8fd21..68acd77354ba 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -63,9 +63,5 @@ EGL_ENTRY(EGLBoolean, eglGetSyncAttribKHR, EGLDisplay, EGLSyncKHR, EGLint,
EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
-#ifndef TARGET_BOARD_SNOWBALL
/* NVIDIA extensions */
-EGL_ENTRY(EGLuint64NV, eglGetSystemTimeFrequencyNV, void)
-EGL_ENTRY(EGLuint64NV, eglGetSystemTimeNV, void)
-#endif
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index fa4959298fb9..652338879ec4 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -2,6 +2,10 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifeq ($(BOARD_HAVE_FMRADIO_SUPPORT),STERICSSON_FMRADIO_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_FMRADIO_SUPPORT
+endif
+
LOCAL_SRC_FILES:= \
AudioFlinger.cpp \
AudioMixer.cpp.arm \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ce701ca297c9..59ef55b9c14f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -242,6 +242,7 @@ AudioFlinger::~AudioFlinger()
audio_hw_device_close(dev);
}
mAudioHwDevs.clear();
+ delete mInputFMStream;
}
audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
@@ -249,8 +250,8 @@ audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
/* first matching HW device is returned */
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
audio_hw_device_t *dev = mAudioHwDevs[i];
- if ((dev->get_supported_devices(dev) & devices) == devices)
- return dev;
+ if ((dev->get_supported_devices(dev) & devices) == devices)
+ return dev;
}
return NULL;
}
@@ -863,6 +864,11 @@ unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
return 0;
}
+size_t AudioFlinger::readInput(uint32_t *input, uint32_t inputClientId, void *buffer, uint32_t bytes, uint32_t *pOverwrittenBytes)
+{
+ return mInputFMStream->stream->read(mInputFMStream->stream, buffer, (size_t)bytes);
+}
+
status_t AudioFlinger::setVoiceVolume(float value)
{
status_t ret = initCheck();
@@ -5062,7 +5068,8 @@ int AudioFlinger::openInput(uint32_t *pDevices,
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
- uint32_t acoustics)
+ uint32_t acoustics,
+ uint32_t *pInputClientId)
{
status_t status;
RecordThread *thread = NULL;
@@ -5089,13 +5096,14 @@ int AudioFlinger::openInput(uint32_t *pDevices,
&channels, &samplingRate,
(audio_in_acoustics_t)acoustics,
&inStream);
- LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
+ LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d, pInputClientId=%p",
inStream,
samplingRate,
format,
channels,
acoustics,
- status);
+ status,
+ pInputClientId);
// If the input could not be opened with the requested parameters and we can handle the conversion internally,
// try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
@@ -5111,8 +5119,13 @@ int AudioFlinger::openInput(uint32_t *pDevices,
&inStream);
}
- if (inStream != NULL) {
- AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
+ if (inStream == NULL) {
+ return 0;
+ }
+
+ AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
+
+ if (inStream != NULL && pInputClientId == NULL) {
int id = nextUniqueId();
// Start record thread
@@ -5136,38 +5149,48 @@ int AudioFlinger::openInput(uint32_t *pDevices,
// notify client processes of the new input creation
thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
return id;
+ } else if (pInputClientId != NULL && *pInputClientId == AUDIO_INPUT_CLIENT_PLAYBACK) {
+ mInputFMStream = input;
+ return (int)input;
}
return 0;
}
-status_t AudioFlinger::closeInput(int input)
+status_t AudioFlinger::closeInput(int input, uint32_t *inputClientId)
{
// keep strong reference on the record thread so that
// it is not destroyed while exit() is executed
- sp <RecordThread> thread;
- {
- Mutex::Autolock _l(mLock);
- thread = checkRecordThread_l(input);
- if (thread == NULL) {
- return BAD_VALUE;
+ if (inputClientId == NULL) {
+ sp <RecordThread> thread;
+ {
+ Mutex::Autolock _l(mLock);
+ thread = checkRecordThread_l(input);
+ if (thread == NULL) {
+ return BAD_VALUE;
+ }
+
+ LOGV("closeInput() %d", input);
+ void *param2 = 0;
+ audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
+ mRecordThreads.removeItem(input);
}
+ thread->exit();
- LOGV("closeInput() %d", input);
- void *param2 = 0;
- audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
- mRecordThreads.removeItem(input);
+ AudioStreamIn *in = thread->clearInput();
+ // from now on thread->mInput is NULL
+ in->hwDev->close_input_stream(in->hwDev, in->stream);
+ delete in;
+ } else if (inputClientId != NULL && *inputClientId == AUDIO_INPUT_CLIENT_PLAYBACK) {
+ AudioStreamIn *in = (AudioStreamIn *)input;
+ in->hwDev->close_input_stream(in->hwDev, in->stream);
+ delete in;
}
- thread->exit();
-
- AudioStreamIn *in = thread->clearInput();
- // from now on thread->mInput is NULL
- in->hwDev->close_input_stream(in->hwDev, in->stream);
- delete in;
return NO_ERROR;
}
+
status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
{
Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9bd2c7f49302..243bd329a0d9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -137,9 +137,12 @@ public:
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
- uint32_t acoustics);
+ uint32_t acoustics,
+ uint32_t *pInputClientId = NULL);
- virtual status_t closeInput(int input);
+ virtual status_t closeInput(int input, uint32_t *inputClientId = NULL);
+
+ virtual size_t readInput(uint32_t *input, uint32_t inputClientId, void *buffer, uint32_t bytes, uint32_t *pOverwrittenBytes);
virtual status_t setStreamOutput(uint32_t stream, int output);
@@ -1390,6 +1393,7 @@ private:
mutable Mutex mHardwareLock;
audio_hw_device_t* mPrimaryHardwareDev;
+ AudioStreamIn* mInputFMStream;
Vector<audio_hw_device_t*> mAudioHwDevs;
mutable int mHardwareStatus;
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 8da5ca14dd74..15cefc059d5b 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -306,14 +306,15 @@ audio_io_handle_t AudioPolicyService::getInput(int inputSource,
uint32_t format,
uint32_t channels,
audio_in_acoustics_t acoustics,
- int audioSession)
+ int audioSession,
+ audio_input_clients *inputClientId)
{
if (mpAudioPolicy == NULL) {
return 0;
}
Mutex::Autolock _l(mLock);
audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
- format, channels, acoustics);
+ format, channels, acoustics, inputClientId);
if (input == 0) {
return input;
@@ -1411,7 +1412,8 @@ static audio_io_handle_t aps_open_input(void *service,
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
- uint32_t acoustics)
+ uint32_t acoustics,
+ uint32_t *inputClientId)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == NULL) {
@@ -1420,16 +1422,16 @@ static audio_io_handle_t aps_open_input(void *service,
}
return af->openInput(pDevices, pSamplingRate, pFormat, pChannels,
- acoustics);
+ acoustics, inputClientId);
}
-static int aps_close_input(void *service, audio_io_handle_t input)
+static int aps_close_input(void *service, audio_io_handle_t input, uint32_t *inputClientId = NULL)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == NULL)
return PERMISSION_DENIED;
- return af->closeInput(input);
+ return af->closeInput(input, inputClientId);
}
static int aps_set_stream_output(void *service, audio_stream_type_t stream,
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index d898a530cc8c..68448508453a 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -82,7 +82,8 @@ public:
uint32_t channels = 0,
audio_in_acoustics_t acoustics =
(audio_in_acoustics_t)0,
- int audioSession = 0);
+ int audioSession = 0,
+ audio_input_clients *inputClientId = NULL);
virtual status_t startInput(audio_io_handle_t input);
virtual status_t stopInput(audio_io_handle_t input);
virtual void releaseInput(audio_io_handle_t input);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index f1cb50e01d5f..5a084b2ae9d7 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -38,6 +38,10 @@ ifeq ($(BOARD_HAVE_CODEC_SUPPORT),SAMSUNG_CODEC_SUPPORT)
LOCAL_CFLAGS += -DSAMSUNG_CODEC_SUPPORT
endif
+ifeq ($(BOARD_HAVE_CODEC_SUPPORT),STERICSSON_CODEC_SUPPORT)
+ LOCAL_CFLAGS += -DSTERICSSON_CODEC_SUPPORT
+endif
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f94d32149b0f..56c8083a7b1e 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -379,6 +379,8 @@ void DisplayHardware::flip(const Region& dirty) const
if (mHwc->initCheck() == NO_ERROR) {
mHwc->commit();
} else {
+ // Make sure the swapbuffer call is done in sync
+ mNativeWindow->compositionComplete();
eglSwapBuffers(dpy, surface);
}
checkEGLErrors("eglSwapBuffers");
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index be9b2265c7db..186c90cbbd46 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -89,6 +89,7 @@ status_t HWComposer::createWorkList(size_t numLayers) {
free(mList);
size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
mList = (hwc_layer_list_t*)malloc(size);
+ memset(mList, 0, size);
mCapacity = numLayers;
}
mList->flags = HWC_GEOMETRY_CHANGED;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 673fda920a68..c4ec78a5e828 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -244,6 +244,16 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
void Layer::onDraw(const Region& clip) const
{
+ // Convert the texture to a native format if need be.
+ // convert() returns immediately if no conversion is necessary.
+ if (mSurfaceTexture != NULL) {
+ status_t res = mSurfaceTexture->convert();
+ if (res != NO_ERROR) {
+ LOGE("Layer::onDraw: texture conversion failed. "
+ "Texture content for this layer will not be initialized.");
+ }
+ }
+
if (CC_UNLIKELY(mActiveBuffer == 0)) {
// the texture has not been created yet, this Layer has
// in fact never been drawn into. This happens frequently with
@@ -404,7 +414,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
mFlinger->signalEvent();
}
- if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
+ if (mSurfaceTexture->updateTexImage(true) < NO_ERROR) {
// something happened!
recomputeVisibleRegions = true;
return;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0da75c4cacc6..1015e54f2e58 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -436,7 +436,6 @@ bool SurfaceFlinger::threadLoop()
// inform the h/w that we're done compositing
logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
- hw.compositionComplete();
logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
postFramebuffer();
@@ -444,7 +443,6 @@ bool SurfaceFlinger::threadLoop()
logger.log(GraphicLog::SF_REPAINT_DONE, index);
} else {
// pretend we did the post
- hw.compositionComplete();
usleep(16667); // 60 fps period
}
return true;
@@ -816,8 +814,6 @@ void SurfaceFlinger::handleRepaint()
// set the frame buffer
const DisplayHardware& hw(graphicPlane(0).displayHardware());
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
uint32_t flags = hw.getFlags();
if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
@@ -858,8 +854,11 @@ void SurfaceFlinger::handleRepaint()
mDirtyRegion.clear();
}
+static bool checkDrawingWithGL(hwc_layer_t* const layers, size_t layerCount);
+
void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
{
+ bool useGL = true;
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
hwc_layer_t* const cur(hwc.getLayers());
@@ -891,6 +890,22 @@ void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
status_t err = hwc.prepare();
LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+ /*
+ * Check if GL will be used
+ */
+ useGL = checkDrawingWithGL(cur, count);
+
+ if (!useGL) {
+ return;
+ }
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ if (UNLIKELY(!mWormholeRegion.isEmpty())) {
+ // should never happen unless the window manager has a bug
+ // draw something...
+ drawWormhole();
+ }
+
if (err == NO_ERROR) {
// what's happening here is tricky.
// we want to clear all the layers with the CLEAR_FB flags
@@ -958,20 +973,28 @@ void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
}
}
+static bool checkDrawingWithGL(hwc_layer_t* const layers, size_t layerCount)
+{
+ bool useGL = false;
+ if (layers) {
+ for (size_t i=0 ; i<layerCount ; i++) {
+ if (layers[i].compositionType == HWC_FRAMEBUFFER) {
+ useGL = true;
+ }
+ }
+ }
+ return useGL;
+}
+
void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
- if (UNLIKELY(fbLayerCount && !mWormholeRegion.isEmpty())) {
- // should never happen unless the window manager has a bug
- // draw something...
- drawWormhole();
- }
/*
- * and then, render the layers targeted at the framebuffer
+ * render the layers targeted at the framebuffer
*/
hwc_layer_t* const cur(hwc.getLayers());
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
@@ -1778,24 +1801,14 @@ status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
GLuint name, tname;
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
-#ifdef TARGET_BOARD_SNOWBALL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
hw_w, hw_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-#else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
- hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
-#endif
if (glGetError() != GL_NO_ERROR) {
while ( glGetError() != GL_NO_ERROR ) ;
GLint tw = (2 << (31 - clz(hw_w)));
GLint th = (2 << (31 - clz(hw_h)));
-#ifdef TARGET_BOARD_SNOWBALL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-#else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
- tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
-#endif
u = GLfloat(hw_w) / tw;
v = GLfloat(hw_h) / th;
}
@@ -2367,8 +2380,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
glDeleteRenderbuffersOES(1, &tname);
glDeleteFramebuffersOES(1, &name);
- hw.compositionComplete();
-
// LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
return result;
@@ -2586,9 +2597,9 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
- LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
+ LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d, format=%#x) "
"failed (%s), handle=%p",
- w, h, strerror(-err), graphicBuffer->handle);
+ w, h, format, strerror(-err), graphicBuffer->handle);
return 0;
}
return graphicBuffer;