manual merge
Change-Id: I9cdacbf1e445e7f6cf06ad03df541a744c242774
This commit is contained in:
@@ -27062,19 +27062,6 @@
|
|||||||
deprecated="not deprecated"
|
deprecated="not deprecated"
|
||||||
visibility="public"
|
visibility="public"
|
||||||
>
|
>
|
||||||
<method name="setKeyPrefix"
|
|
||||||
return="void"
|
|
||||||
abstract="false"
|
|
||||||
native="false"
|
|
||||||
synchronized="false"
|
|
||||||
static="false"
|
|
||||||
final="false"
|
|
||||||
deprecated="not deprecated"
|
|
||||||
visibility="public"
|
|
||||||
>
|
|
||||||
<parameter name="keyPrefix" type="java.lang.String">
|
|
||||||
</parameter>
|
|
||||||
</method>
|
|
||||||
<method name="writeEntityData"
|
<method name="writeEntityData"
|
||||||
return="int"
|
return="int"
|
||||||
abstract="false"
|
abstract="false"
|
||||||
@@ -27109,28 +27096,6 @@
|
|||||||
<exception name="IOException" type="java.io.IOException">
|
<exception name="IOException" type="java.io.IOException">
|
||||||
</exception>
|
</exception>
|
||||||
</method>
|
</method>
|
||||||
<field name="OP_DELETE"
|
|
||||||
type="int"
|
|
||||||
transient="false"
|
|
||||||
volatile="false"
|
|
||||||
value="2"
|
|
||||||
static="true"
|
|
||||||
final="true"
|
|
||||||
deprecated="not deprecated"
|
|
||||||
visibility="public"
|
|
||||||
>
|
|
||||||
</field>
|
|
||||||
<field name="OP_UPDATE"
|
|
||||||
type="int"
|
|
||||||
transient="false"
|
|
||||||
volatile="false"
|
|
||||||
value="1"
|
|
||||||
static="true"
|
|
||||||
final="true"
|
|
||||||
deprecated="not deprecated"
|
|
||||||
visibility="public"
|
|
||||||
>
|
|
||||||
</field>
|
|
||||||
</class>
|
</class>
|
||||||
<interface name="BackupHelper"
|
<interface name="BackupHelper"
|
||||||
abstract="true"
|
abstract="true"
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ int main(int argc, char **argv) {
|
|||||||
OMXClient client;
|
OMXClient client;
|
||||||
CHECK_EQ(client.connect(), OK);
|
CHECK_EQ(client.connect(), OK);
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
sp<MediaSource> source = createSource(argv[1]);
|
sp<MediaSource> source = createSource(argv[1]);
|
||||||
|
|
||||||
if (source == NULL) {
|
if (source == NULL) {
|
||||||
@@ -165,14 +165,15 @@ int main(int argc, char **argv) {
|
|||||||
success = success && meta->findInt32(kKeyHeight, &height);
|
success = success && meta->findInt32(kKeyHeight, &height);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
#else
|
#else
|
||||||
int width = 800;
|
int width = 720;
|
||||||
int height = 480;
|
int height = 480;
|
||||||
sp<MediaSource> decoder = new DummySource(width, height);
|
sp<MediaSource> decoder = new DummySource(width, height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sp<MetaData> enc_meta = new MetaData;
|
sp<MetaData> enc_meta = new MetaData;
|
||||||
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
|
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
|
||||||
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
|
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
|
||||||
|
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
|
||||||
enc_meta->setInt32(kKeyWidth, width);
|
enc_meta->setInt32(kKeyWidth, width);
|
||||||
enc_meta->setInt32(kKeyHeight, height);
|
enc_meta->setInt32(kKeyHeight, height);
|
||||||
|
|
||||||
@@ -213,6 +214,8 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
CameraSource *source = CameraSource::Create();
|
CameraSource *source = CameraSource::Create();
|
||||||
|
source->start();
|
||||||
|
|
||||||
printf("source = %p\n", source);
|
printf("source = %p\n", source);
|
||||||
|
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
@@ -227,6 +230,8 @@ int main(int argc, char **argv) {
|
|||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source->stop();
|
||||||
|
|
||||||
delete source;
|
delete source;
|
||||||
source = NULL;
|
source = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ import java.io.IOException;
|
|||||||
public class BackupDataOutput {
|
public class BackupDataOutput {
|
||||||
int mBackupWriter;
|
int mBackupWriter;
|
||||||
|
|
||||||
public static final int OP_UPDATE = 1;
|
|
||||||
public static final int OP_DELETE = 2;
|
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public BackupDataOutput(FileDescriptor fd) {
|
public BackupDataOutput(FileDescriptor fd) {
|
||||||
if (fd == null) throw new NullPointerException();
|
if (fd == null) throw new NullPointerException();
|
||||||
@@ -71,6 +68,7 @@ public class BackupDataOutput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
public void setKeyPrefix(String keyPrefix) {
|
public void setKeyPrefix(String keyPrefix) {
|
||||||
setKeyPrefix_native(mBackupWriter, keyPrefix);
|
setKeyPrefix_native(mBackupWriter, keyPrefix);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -574,7 +574,9 @@ public class Browser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request all icons from the database.
|
* Request all icons from the database. This call must either be called
|
||||||
|
* in the main thread or have had Looper.prepare() invoked in the calling
|
||||||
|
* thread.
|
||||||
* Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
|
* Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
|
||||||
* @param cr The ContentResolver used to access the database.
|
* @param cr The ContentResolver used to access the database.
|
||||||
* @param where Clause to be used to limit the query from the database.
|
* @param where Clause to be used to limit the query from the database.
|
||||||
@@ -584,25 +586,8 @@ public class Browser {
|
|||||||
*/
|
*/
|
||||||
public static final void requestAllIcons(ContentResolver cr, String where,
|
public static final void requestAllIcons(ContentResolver cr, String where,
|
||||||
WebIconDatabase.IconListener listener) {
|
WebIconDatabase.IconListener listener) {
|
||||||
Cursor c = null;
|
WebIconDatabase.getInstance()
|
||||||
try {
|
.bulkRequestIconForPageUrl(cr, where, listener);
|
||||||
c = cr.query(
|
|
||||||
BOOKMARKS_URI,
|
|
||||||
new String[] { BookmarkColumns.URL },
|
|
||||||
where, null, null);
|
|
||||||
if (c.moveToFirst()) {
|
|
||||||
final WebIconDatabase db = WebIconDatabase.getInstance();
|
|
||||||
do {
|
|
||||||
db.requestIconForPageUrl(c.getString(0), listener);
|
|
||||||
} while (c.moveToNext());
|
|
||||||
}
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Log.e(LOGTAG, "requestAllIcons", e);
|
|
||||||
} finally {
|
|
||||||
if (c != null) {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BookmarkColumns implements BaseColumns {
|
public static class BookmarkColumns implements BaseColumns {
|
||||||
|
|||||||
@@ -16,10 +16,15 @@
|
|||||||
|
|
||||||
package android.webkit;
|
package android.webkit;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.graphics.Bitmap;
|
import android.provider.Browser;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +35,7 @@ import java.util.Vector;
|
|||||||
* single object.
|
* single object.
|
||||||
*/
|
*/
|
||||||
public final class WebIconDatabase {
|
public final class WebIconDatabase {
|
||||||
|
private static final String LOGTAG = "WebIconDatabase";
|
||||||
// Global instance of a WebIconDatabase
|
// Global instance of a WebIconDatabase
|
||||||
private static WebIconDatabase sIconDatabase;
|
private static WebIconDatabase sIconDatabase;
|
||||||
// EventHandler for handling messages before and after the WebCore thread is
|
// EventHandler for handling messages before and after the WebCore thread is
|
||||||
@@ -45,6 +51,7 @@ public final class WebIconDatabase {
|
|||||||
static final int REQUEST_ICON = 3;
|
static final int REQUEST_ICON = 3;
|
||||||
static final int RETAIN_ICON = 4;
|
static final int RETAIN_ICON = 4;
|
||||||
static final int RELEASE_ICON = 5;
|
static final int RELEASE_ICON = 5;
|
||||||
|
static final int BULK_REQUEST_ICON = 6;
|
||||||
// Message for dispatching icon request results
|
// Message for dispatching icon request results
|
||||||
private static final int ICON_RESULT = 10;
|
private static final int ICON_RESULT = 10;
|
||||||
// Actual handler that runs in WebCore thread
|
// Actual handler that runs in WebCore thread
|
||||||
@@ -100,12 +107,11 @@ public final class WebIconDatabase {
|
|||||||
case REQUEST_ICON:
|
case REQUEST_ICON:
|
||||||
IconListener l = (IconListener) msg.obj;
|
IconListener l = (IconListener) msg.obj;
|
||||||
String url = msg.getData().getString("url");
|
String url = msg.getData().getString("url");
|
||||||
Bitmap icon = nativeIconForPageUrl(url);
|
requestIconAndSendResult(url, l);
|
||||||
if (icon != null) {
|
break;
|
||||||
EventHandler.this.sendMessage(
|
|
||||||
Message.obtain(null, ICON_RESULT,
|
case BULK_REQUEST_ICON:
|
||||||
new IconResult(url, icon, l)));
|
bulkRequestIcons(msg);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETAIN_ICON:
|
case RETAIN_ICON:
|
||||||
@@ -126,6 +132,10 @@ public final class WebIconDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized boolean hasHandler() {
|
||||||
|
return mHandler != null;
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void postMessage(Message msg) {
|
private synchronized void postMessage(Message msg) {
|
||||||
if (mMessages != null) {
|
if (mMessages != null) {
|
||||||
mMessages.add(msg);
|
mMessages.add(msg);
|
||||||
@@ -133,6 +143,39 @@ public final class WebIconDatabase {
|
|||||||
mHandler.sendMessage(msg);
|
mHandler.sendMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bulkRequestIcons(Message msg) {
|
||||||
|
HashMap map = (HashMap) msg.obj;
|
||||||
|
IconListener listener = (IconListener) map.get("listener");
|
||||||
|
ContentResolver cr = (ContentResolver) map.get("contentResolver");
|
||||||
|
String where = (String) map.get("where");
|
||||||
|
|
||||||
|
Cursor c = null;
|
||||||
|
try {
|
||||||
|
c = cr.query(
|
||||||
|
Browser.BOOKMARKS_URI,
|
||||||
|
new String[] { Browser.BookmarkColumns.URL },
|
||||||
|
where, null, null);
|
||||||
|
if (c.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
String url = c.getString(0);
|
||||||
|
requestIconAndSendResult(url, listener);
|
||||||
|
} while (c.moveToNext());
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
Log.e(LOGTAG, "BulkRequestIcons", e);
|
||||||
|
} finally {
|
||||||
|
if (c != null) c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestIconAndSendResult(String url, IconListener listener) {
|
||||||
|
Bitmap icon = nativeIconForPageUrl(url);
|
||||||
|
if (icon != null) {
|
||||||
|
sendMessage(obtainMessage(ICON_RESULT,
|
||||||
|
new IconResult(url, icon, listener)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,6 +235,30 @@ public final class WebIconDatabase {
|
|||||||
mEventHandler.postMessage(msg);
|
mEventHandler.postMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@hide}
|
||||||
|
*/
|
||||||
|
public void bulkRequestIconForPageUrl(ContentResolver cr, String where,
|
||||||
|
IconListener listener) {
|
||||||
|
if (listener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case situation: we don't want to add this message to the
|
||||||
|
// queue if there is no handler because we may never have a real
|
||||||
|
// handler to service the messages and the cursor will never get
|
||||||
|
// closed.
|
||||||
|
if (mEventHandler.hasHandler()) {
|
||||||
|
// Don't use Bundle as it is parcelable.
|
||||||
|
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||||
|
map.put("contentResolver", cr);
|
||||||
|
map.put("where", where);
|
||||||
|
map.put("listener", listener);
|
||||||
|
Message msg =
|
||||||
|
Message.obtain(null, EventHandler.BULK_REQUEST_ICON, map);
|
||||||
|
mEventHandler.postMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retain the icon for the given page url.
|
* Retain the icon for the given page url.
|
||||||
* @param url The page's url.
|
* @param url The page's url.
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ screen. </p>
|
|||||||
generalized densities: high, medium, and low. Applications can provide custom
|
generalized densities: high, medium, and low. Applications can provide custom
|
||||||
resources for each of these three densities — the platform handles the
|
resources for each of these three densities — the platform handles the
|
||||||
scaling of the resources up or down to meet the actual screen density. </p></dd>
|
scaling of the resources up or down to meet the actual screen density. </p></dd>
|
||||||
<dt><em>Density independent pixel (dip)</em></dt>
|
<dt><em>Density-independent pixel (dip)</em></dt>
|
||||||
<dd>A virtual pixel unit that applications can use in defining their UI, to
|
<dd>A virtual pixel unit that applications can use in defining their UI, to
|
||||||
express layout dimensions or position in a density-independent way.
|
express layout dimensions or position in a density-independent way.
|
||||||
<p>The density-independent pixel is equivalent to one physical pixel on a 160
|
<p>The density-independent pixel is equivalent to one physical pixel on a 160
|
||||||
@@ -432,7 +432,7 @@ does this in three ways: </p>
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Through pre-scaling of drawable resources (scaled at resource loading
|
<li>Through pre-scaling of drawable resources (scaled at resource loading
|
||||||
time)</li>
|
time)</li>
|
||||||
<li>Through auto-scaling of device-independent pixel (dip) values used in
|
<li>Through auto-scaling of density-independent pixel (dip) values used in
|
||||||
layouts</li>
|
layouts</li>
|
||||||
<li>Through auto-scaling of absolute pixel values used in the application (only
|
<li>Through auto-scaling of absolute pixel values used in the application (only
|
||||||
needed if the application has set <code>android:anyDensity="false"</code> in its
|
needed if the application has set <code>android:anyDensity="false"</code> in its
|
||||||
@@ -573,7 +573,7 @@ installing the application on small-screen devices. </li>
|
|||||||
are signaling to the platform that your application wants to manage its UI by
|
are signaling to the platform that your application wants to manage its UI by
|
||||||
itself, for all screen densities, using the actual screen dimensions and pixels.
|
itself, for all screen densities, using the actual screen dimensions and pixels.
|
||||||
In this case, the application must ensure that it declares its UI dimensions
|
In this case, the application must ensure that it declares its UI dimensions
|
||||||
using device-independent pixels and scales any actual pixel values or math by
|
using density-independent pixels and scales any actual pixel values or math by
|
||||||
the scaling factor available from
|
the scaling factor available from
|
||||||
{@link android.util.DisplayMetrics#density android.util.DisplayMetrics.density}.</p>
|
{@link android.util.DisplayMetrics#density android.util.DisplayMetrics.density}.</p>
|
||||||
|
|
||||||
|
|||||||
@@ -42,14 +42,12 @@ protected:
|
|||||||
virtual ~AMRWriter();
|
virtual ~AMRWriter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex mLock;
|
|
||||||
|
|
||||||
FILE *mFile;
|
FILE *mFile;
|
||||||
status_t mInitCheck;
|
status_t mInitCheck;
|
||||||
sp<MediaSource> mSource;
|
sp<MediaSource> mSource;
|
||||||
bool mStarted;
|
bool mStarted;
|
||||||
volatile bool mDone;
|
volatile bool mDone;
|
||||||
bool mReachedEOS;
|
volatile bool mReachedEOS;
|
||||||
pthread_t mThread;
|
pthread_t mThread;
|
||||||
|
|
||||||
static void *ThreadWrapper(void *);
|
static void *ThreadWrapper(void *);
|
||||||
|
|||||||
@@ -2090,14 +2090,18 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
Log.i(TAG, " AudioFocus abandonAudioFocus() from " + clientId);
|
Log.i(TAG, " AudioFocus abandonAudioFocus() from " + clientId);
|
||||||
|
|
||||||
// this will take care of notifying the new focus owner if needed
|
// this will take care of notifying the new focus owner if needed
|
||||||
removeFocusStackEntry(clientId, true);
|
synchronized(mFocusStack) {
|
||||||
|
removeFocusStackEntry(clientId, true);
|
||||||
|
}
|
||||||
|
|
||||||
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
|
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void unregisterAudioFocusClient(String clientId) {
|
public void unregisterAudioFocusClient(String clientId) {
|
||||||
removeFocusStackEntry(clientId, false);
|
synchronized(mFocusStack) {
|
||||||
|
removeFocusStackEntry(clientId, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -228,14 +228,10 @@ MediaPlayerService::~MediaPlayerService()
|
|||||||
|
|
||||||
sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
|
sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
|
||||||
{
|
{
|
||||||
#ifndef NO_OPENCORE
|
|
||||||
sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
|
sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
|
||||||
wp<MediaRecorderClient> w = recorder;
|
wp<MediaRecorderClient> w = recorder;
|
||||||
Mutex::Autolock lock(mLock);
|
Mutex::Autolock lock(mLock);
|
||||||
mMediaRecorderClients.add(w);
|
mMediaRecorderClients.add(w);
|
||||||
#else
|
|
||||||
sp<MediaRecorderClient> recorder = NULL;
|
|
||||||
#endif
|
|
||||||
LOGV("Create new media recorder client from pid %d", pid);
|
LOGV("Create new media recorder client from pid %d", pid);
|
||||||
return recorder;
|
return recorder;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ status_t AMRWriter::initCheck() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t AMRWriter::addSource(const sp<MediaSource> &source) {
|
status_t AMRWriter::addSource(const sp<MediaSource> &source) {
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
|
|
||||||
if (mInitCheck != OK) {
|
if (mInitCheck != OK) {
|
||||||
return mInitCheck;
|
return mInitCheck;
|
||||||
}
|
}
|
||||||
@@ -95,8 +93,6 @@ status_t AMRWriter::addSource(const sp<MediaSource> &source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t AMRWriter::start() {
|
status_t AMRWriter::start() {
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
|
|
||||||
if (mInitCheck != OK) {
|
if (mInitCheck != OK) {
|
||||||
return mInitCheck;
|
return mInitCheck;
|
||||||
}
|
}
|
||||||
@@ -127,16 +123,12 @@ status_t AMRWriter::start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AMRWriter::stop() {
|
void AMRWriter::stop() {
|
||||||
{
|
if (!mStarted) {
|
||||||
Mutex::Autolock autoLock(mLock);
|
return;
|
||||||
|
|
||||||
if (!mStarted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDone = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDone = true;
|
||||||
|
|
||||||
void *dummy;
|
void *dummy;
|
||||||
pthread_join(mThread, &dummy);
|
pthread_join(mThread, &dummy);
|
||||||
|
|
||||||
@@ -153,13 +145,7 @@ void *AMRWriter::ThreadWrapper(void *me) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AMRWriter::threadFunc() {
|
void AMRWriter::threadFunc() {
|
||||||
for (;;) {
|
while (!mDone) {
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
|
|
||||||
if (mDone) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaBuffer *buffer;
|
MediaBuffer *buffer;
|
||||||
status_t err = mSource->read(&buffer);
|
status_t err = mSource->read(&buffer);
|
||||||
|
|
||||||
@@ -184,12 +170,10 @@ void AMRWriter::threadFunc() {
|
|||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
mReachedEOS = true;
|
mReachedEOS = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AMRWriter::reachedEOS() {
|
bool AMRWriter::reachedEOS() {
|
||||||
Mutex::Autolock autoLock(mLock);
|
|
||||||
return mReachedEOS;
|
return mReachedEOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,13 +142,6 @@ CameraSource::CameraSource(const sp<Camera> &camera)
|
|||||||
mFirstFrameTimeUs(0),
|
mFirstFrameTimeUs(0),
|
||||||
mNumFrames(0),
|
mNumFrames(0),
|
||||||
mStarted(false) {
|
mStarted(false) {
|
||||||
char value[PROPERTY_VALUE_MAX];
|
|
||||||
if (property_get("ro.hardware", value, NULL) && !strcmp(value, "sholes")) {
|
|
||||||
// The hardware encoder(s) do not support yuv420, but only YCbYCr,
|
|
||||||
// fortunately the camera also supports this, so we needn't transcode.
|
|
||||||
mCamera->setParameters(String8("preview-format=yuv422i-yuyv"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String8 s = mCamera->getParameters();
|
String8 s = mCamera->getParameters();
|
||||||
printf("params: \"%s\"\n", s.string());
|
printf("params: \"%s\"\n", s.string());
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <media/stagefright/MetaData.h>
|
#include <media/stagefright/MetaData.h>
|
||||||
#include <media/stagefright/MediaDebug.h>
|
#include <media/stagefright/MediaDebug.h>
|
||||||
#include <media/stagefright/MediaDefs.h>
|
#include <media/stagefright/MediaDefs.h>
|
||||||
|
#include <media/stagefright/MediaErrors.h>
|
||||||
#include <media/stagefright/MediaSource.h>
|
#include <media/stagefright/MediaSource.h>
|
||||||
#include <media/stagefright/Utils.h>
|
#include <media/stagefright/Utils.h>
|
||||||
|
|
||||||
@@ -59,16 +60,22 @@ private:
|
|||||||
|
|
||||||
void *mCodecSpecificData;
|
void *mCodecSpecificData;
|
||||||
size_t mCodecSpecificDataSize;
|
size_t mCodecSpecificDataSize;
|
||||||
|
bool mGotAllCodecSpecificData;
|
||||||
|
|
||||||
bool mReachedEOS;
|
bool mReachedEOS;
|
||||||
|
|
||||||
static void *ThreadWrapper(void *me);
|
static void *ThreadWrapper(void *me);
|
||||||
void threadEntry();
|
void threadEntry();
|
||||||
|
|
||||||
|
status_t makeAVCCodecSpecificData(
|
||||||
|
const uint8_t *data, size_t size);
|
||||||
|
|
||||||
Track(const Track &);
|
Track(const Track &);
|
||||||
Track &operator=(const Track &);
|
Track &operator=(const Track &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define USE_NALLEN_FOUR 1
|
||||||
|
|
||||||
MPEG4Writer::MPEG4Writer(const char *filename)
|
MPEG4Writer::MPEG4Writer(const char *filename)
|
||||||
: mFile(fopen(filename, "wb")),
|
: mFile(fopen(filename, "wb")),
|
||||||
mOffset(0),
|
mOffset(0),
|
||||||
@@ -213,23 +220,55 @@ off_t MPEG4Writer::addSample(MediaBuffer *buffer) {
|
|||||||
return old_offset;
|
return old_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void StripStartcode(MediaBuffer *buffer) {
|
||||||
|
if (buffer->range_length() < 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *ptr =
|
||||||
|
(const uint8_t *)buffer->data() + buffer->range_offset();
|
||||||
|
|
||||||
|
if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
|
||||||
|
buffer->set_range(
|
||||||
|
buffer->range_offset() + 4, buffer->range_length() - 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
off_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
|
off_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
|
||||||
Mutex::Autolock autoLock(mLock);
|
Mutex::Autolock autoLock(mLock);
|
||||||
|
|
||||||
|
StripStartcode(buffer);
|
||||||
|
|
||||||
off_t old_offset = mOffset;
|
off_t old_offset = mOffset;
|
||||||
|
|
||||||
size_t length = buffer->range_length();
|
size_t length = buffer->range_length();
|
||||||
|
|
||||||
|
#if USE_NALLEN_FOUR
|
||||||
|
uint8_t x = length >> 24;
|
||||||
|
fwrite(&x, 1, 1, mFile);
|
||||||
|
x = (length >> 16) & 0xff;
|
||||||
|
fwrite(&x, 1, 1, mFile);
|
||||||
|
x = (length >> 8) & 0xff;
|
||||||
|
fwrite(&x, 1, 1, mFile);
|
||||||
|
x = length & 0xff;
|
||||||
|
fwrite(&x, 1, 1, mFile);
|
||||||
|
#else
|
||||||
CHECK(length < 65536);
|
CHECK(length < 65536);
|
||||||
|
|
||||||
uint8_t x = length >> 8;
|
uint8_t x = length >> 8;
|
||||||
fwrite(&x, 1, 1, mFile);
|
fwrite(&x, 1, 1, mFile);
|
||||||
x = length & 0xff;
|
x = length & 0xff;
|
||||||
fwrite(&x, 1, 1, mFile);
|
fwrite(&x, 1, 1, mFile);
|
||||||
|
#endif
|
||||||
|
|
||||||
fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
|
fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
|
||||||
1, length, mFile);
|
1, length, mFile);
|
||||||
|
|
||||||
|
#if USE_NALLEN_FOUR
|
||||||
|
mOffset += length + 4;
|
||||||
|
#else
|
||||||
mOffset += length + 2;
|
mOffset += length + 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
return old_offset;
|
return old_offset;
|
||||||
}
|
}
|
||||||
@@ -320,6 +359,7 @@ MPEG4Writer::Track::Track(
|
|||||||
mMaxTimeStampUs(0),
|
mMaxTimeStampUs(0),
|
||||||
mCodecSpecificData(NULL),
|
mCodecSpecificData(NULL),
|
||||||
mCodecSpecificDataSize(0),
|
mCodecSpecificDataSize(0),
|
||||||
|
mGotAllCodecSpecificData(false),
|
||||||
mReachedEOS(false) {
|
mReachedEOS(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,6 +420,104 @@ void *MPEG4Writer::Track::ThreadWrapper(void *me) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
static void hexdump(const void *_data, size_t size) {
|
||||||
|
const uint8_t *data = (const uint8_t *)_data;
|
||||||
|
size_t offset = 0;
|
||||||
|
while (offset < size) {
|
||||||
|
printf("0x%04x ", offset);
|
||||||
|
|
||||||
|
size_t n = size - offset;
|
||||||
|
if (n > 16) {
|
||||||
|
n = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 16; ++i) {
|
||||||
|
if (i == 8) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset + i < size) {
|
||||||
|
printf("%02x ", data[offset + i]);
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
if (isprint(data[offset + i])) {
|
||||||
|
printf("%c", data[offset + i]);
|
||||||
|
} else {
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
offset += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
|
||||||
|
const uint8_t *data, size_t size) {
|
||||||
|
// hexdump(data, size);
|
||||||
|
|
||||||
|
if (mCodecSpecificData != NULL) {
|
||||||
|
LOGE("Already have codec specific data");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
|
||||||
|
LOGE("Must start with a start code");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t picParamOffset = 4;
|
||||||
|
while (picParamOffset + 3 < size
|
||||||
|
&& memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
|
||||||
|
++picParamOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (picParamOffset + 3 >= size) {
|
||||||
|
LOGE("Could not find start-code for pictureParameterSet");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t seqParamSetLength = picParamOffset - 4;
|
||||||
|
size_t picParamSetLength = size - picParamOffset - 4;
|
||||||
|
|
||||||
|
mCodecSpecificDataSize =
|
||||||
|
6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
|
||||||
|
|
||||||
|
mCodecSpecificData = malloc(mCodecSpecificDataSize);
|
||||||
|
uint8_t *header = (uint8_t *)mCodecSpecificData;
|
||||||
|
header[0] = 1;
|
||||||
|
header[1] = 0x42; // profile
|
||||||
|
header[2] = 0x80;
|
||||||
|
header[3] = 0x1e; // level
|
||||||
|
|
||||||
|
#if USE_NALLEN_FOUR
|
||||||
|
header[4] = 0xfc | 3; // length size == 4 bytes
|
||||||
|
#else
|
||||||
|
header[4] = 0xfc | 1; // length size == 2 bytes
|
||||||
|
#endif
|
||||||
|
|
||||||
|
header[5] = 0xe0 | 1;
|
||||||
|
header[6] = seqParamSetLength >> 8;
|
||||||
|
header[7] = seqParamSetLength & 0xff;
|
||||||
|
memcpy(&header[8], &data[4], seqParamSetLength);
|
||||||
|
header += 8 + seqParamSetLength;
|
||||||
|
header[0] = 1;
|
||||||
|
header[1] = picParamSetLength >> 8;
|
||||||
|
header[2] = picParamSetLength & 0xff;
|
||||||
|
memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
void MPEG4Writer::Track::threadEntry() {
|
void MPEG4Writer::Track::threadEntry() {
|
||||||
sp<MetaData> meta = mSource->getFormat();
|
sp<MetaData> meta = mSource->getFormat();
|
||||||
const char *mime;
|
const char *mime;
|
||||||
@@ -399,54 +537,40 @@ void MPEG4Writer::Track::threadEntry() {
|
|||||||
|
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
if (is_avc && count < 3) {
|
int32_t isCodecConfig;
|
||||||
size_t size = buffer->range_length();
|
if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
|
||||||
|
&& isCodecConfig) {
|
||||||
|
CHECK(!mGotAllCodecSpecificData);
|
||||||
|
|
||||||
switch (count) {
|
if (is_avc) {
|
||||||
case 1:
|
status_t err = makeAVCCodecSpecificData(
|
||||||
{
|
(const uint8_t *)buffer->data()
|
||||||
CHECK_EQ(mCodecSpecificData, NULL);
|
+ buffer->range_offset(),
|
||||||
mCodecSpecificData = malloc(size + 8);
|
buffer->range_length());
|
||||||
uint8_t *header = (uint8_t *)mCodecSpecificData;
|
|
||||||
header[0] = 1;
|
|
||||||
header[1] = 0x42; // profile
|
|
||||||
header[2] = 0x80;
|
|
||||||
header[3] = 0x1e; // level
|
|
||||||
header[4] = 0xfc | 3;
|
|
||||||
header[5] = 0xe0 | 1;
|
|
||||||
header[6] = size >> 8;
|
|
||||||
header[7] = size & 0xff;
|
|
||||||
memcpy(&header[8],
|
|
||||||
(const uint8_t *)buffer->data() + buffer->range_offset(),
|
|
||||||
size);
|
|
||||||
|
|
||||||
mCodecSpecificDataSize = size + 8;
|
if (err != OK) {
|
||||||
break;
|
LOGE("failed to parse avc codec specific data.");
|
||||||
}
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
size_t offset = mCodecSpecificDataSize;
|
|
||||||
mCodecSpecificDataSize += size + 3;
|
|
||||||
mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
|
|
||||||
uint8_t *header = (uint8_t *)mCodecSpecificData;
|
|
||||||
header[offset] = 1;
|
|
||||||
header[offset + 1] = size >> 8;
|
|
||||||
header[offset + 2] = size & 0xff;
|
|
||||||
memcpy(&header[offset + 3],
|
|
||||||
(const uint8_t *)buffer->data() + buffer->range_offset(),
|
|
||||||
size);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (is_mpeg4) {
|
||||||
|
mCodecSpecificDataSize = buffer->range_length();
|
||||||
|
mCodecSpecificData = malloc(mCodecSpecificDataSize);
|
||||||
|
memcpy(mCodecSpecificData,
|
||||||
|
(const uint8_t *)buffer->data()
|
||||||
|
+ buffer->range_offset(),
|
||||||
|
buffer->range_length());
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->release();
|
buffer->release();
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
|
|
||||||
|
mGotAllCodecSpecificData = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
} else if (!mGotAllCodecSpecificData &&
|
||||||
|
count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
|
||||||
|
// The TI mpeg4 encoder does not properly set the
|
||||||
|
// codec-specific-data flag.
|
||||||
|
|
||||||
if (mCodecSpecificData == NULL && is_mpeg4) {
|
|
||||||
const uint8_t *data =
|
const uint8_t *data =
|
||||||
(const uint8_t *)buffer->data() + buffer->range_offset();
|
(const uint8_t *)buffer->data() + buffer->range_offset();
|
||||||
|
|
||||||
@@ -474,13 +598,74 @@ void MPEG4Writer::Track::threadEntry() {
|
|||||||
memcpy(mCodecSpecificData, data, offset);
|
memcpy(mCodecSpecificData, data, offset);
|
||||||
|
|
||||||
buffer->set_range(buffer->range_offset() + offset, size - offset);
|
buffer->set_range(buffer->range_offset() + offset, size - offset);
|
||||||
|
|
||||||
|
if (size == offset) {
|
||||||
|
buffer->release();
|
||||||
|
buffer = NULL;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGotAllCodecSpecificData = true;
|
||||||
|
} else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
|
||||||
|
// The TI video encoder does not flag codec specific data
|
||||||
|
// as such and also splits up SPS and PPS across two buffers.
|
||||||
|
|
||||||
|
const uint8_t *data =
|
||||||
|
(const uint8_t *)buffer->data() + buffer->range_offset();
|
||||||
|
|
||||||
|
size_t size = buffer->range_length();
|
||||||
|
|
||||||
|
CHECK(count == 2 || mCodecSpecificData == NULL);
|
||||||
|
|
||||||
|
size_t offset = mCodecSpecificDataSize;
|
||||||
|
mCodecSpecificDataSize += size + 4;
|
||||||
|
mCodecSpecificData =
|
||||||
|
realloc(mCodecSpecificData, mCodecSpecificDataSize);
|
||||||
|
|
||||||
|
memcpy((uint8_t *)mCodecSpecificData + offset,
|
||||||
|
"\x00\x00\x00\x01", 4);
|
||||||
|
|
||||||
|
memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
|
||||||
|
|
||||||
|
buffer->release();
|
||||||
|
buffer = NULL;
|
||||||
|
|
||||||
|
if (count == 2) {
|
||||||
|
void *tmp = mCodecSpecificData;
|
||||||
|
size = mCodecSpecificDataSize;
|
||||||
|
mCodecSpecificData = NULL;
|
||||||
|
mCodecSpecificDataSize = 0;
|
||||||
|
|
||||||
|
status_t err = makeAVCCodecSpecificData(
|
||||||
|
(const uint8_t *)tmp, size);
|
||||||
|
|
||||||
|
free(tmp);
|
||||||
|
tmp = NULL;
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
LOGE("failed to parse avc codec specific data.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGotAllCodecSpecificData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
|
off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
|
||||||
: mOwner->addSample(buffer);
|
: mOwner->addSample(buffer);
|
||||||
|
|
||||||
SampleInfo info;
|
SampleInfo info;
|
||||||
info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length();
|
info.size = is_avc
|
||||||
|
#if USE_NALLEN_FOUR
|
||||||
|
? buffer->range_length() + 4
|
||||||
|
#else
|
||||||
|
? buffer->range_length() + 2
|
||||||
|
#endif
|
||||||
|
: buffer->range_length();
|
||||||
|
|
||||||
info.offset = offset;
|
info.offset = offset;
|
||||||
|
|
||||||
int64_t timestampUs;
|
int64_t timestampUs;
|
||||||
@@ -733,19 +918,29 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
|
|||||||
|
|
||||||
mOwner->beginBox("stts");
|
mOwner->beginBox("stts");
|
||||||
mOwner->writeInt32(0); // version=0, flags=0
|
mOwner->writeInt32(0); // version=0, flags=0
|
||||||
mOwner->writeInt32(mSampleInfos.size() - 1);
|
mOwner->writeInt32(mSampleInfos.size());
|
||||||
|
|
||||||
List<SampleInfo>::iterator it = mSampleInfos.begin();
|
List<SampleInfo>::iterator it = mSampleInfos.begin();
|
||||||
int64_t last = (*it).timestamp;
|
int64_t last = (*it).timestamp;
|
||||||
|
int64_t lastDuration = 1;
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
while (it != mSampleInfos.end()) {
|
while (it != mSampleInfos.end()) {
|
||||||
mOwner->writeInt32(1);
|
mOwner->writeInt32(1);
|
||||||
mOwner->writeInt32((*it).timestamp - last);
|
lastDuration = (*it).timestamp - last;
|
||||||
|
mOwner->writeInt32(lastDuration);
|
||||||
|
|
||||||
last = (*it).timestamp;
|
last = (*it).timestamp;
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't really know how long the last frame lasts, since
|
||||||
|
// there is no frame time after it, just repeat the previous
|
||||||
|
// frame's duration.
|
||||||
|
mOwner->writeInt32(1);
|
||||||
|
mOwner->writeInt32(lastDuration);
|
||||||
|
|
||||||
mOwner->endBox(); // stts
|
mOwner->endBox(); // stts
|
||||||
|
|
||||||
mOwner->beginBox("stsz");
|
mOwner->beginBox("stsz");
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ static const CodecInfo kEncoderInfo[] = {
|
|||||||
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
|
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
|
||||||
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
|
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
|
||||||
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
|
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
|
||||||
|
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
|
||||||
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
|
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
|
||||||
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
|
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
|
||||||
};
|
};
|
||||||
@@ -679,6 +680,7 @@ static size_t getFrameSize(
|
|||||||
case OMX_COLOR_FormatCbYCrY:
|
case OMX_COLOR_FormatCbYCrY:
|
||||||
return width * height * 2;
|
return width * height * 2;
|
||||||
|
|
||||||
|
case OMX_COLOR_FormatYUV420Planar:
|
||||||
case OMX_COLOR_FormatYUV420SemiPlanar:
|
case OMX_COLOR_FormatYUV420SemiPlanar:
|
||||||
return (width * height * 3) / 2;
|
return (width * height * 3) / 2;
|
||||||
|
|
||||||
@@ -706,7 +708,7 @@ void OMXCodec::setVideoInputFormat(
|
|||||||
|
|
||||||
OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
|
OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
|
||||||
if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
|
if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
|
||||||
colorFormat = OMX_COLOR_FormatYCbYCr;
|
colorFormat = OMX_COLOR_FormatYUV420Planar;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_EQ(setVideoPortFormatType(
|
CHECK_EQ(setVideoPortFormatType(
|
||||||
@@ -764,6 +766,14 @@ void OMXCodec::setVideoInputFormat(
|
|||||||
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||||
CHECK_EQ(err, OK);
|
CHECK_EQ(err, OK);
|
||||||
|
|
||||||
|
err = mOMX->getParameter(
|
||||||
|
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||||
|
CHECK_EQ(err, OK);
|
||||||
|
|
||||||
|
err = mOMX->setParameter(
|
||||||
|
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||||
|
CHECK_EQ(err, OK);
|
||||||
|
|
||||||
switch (compressionFormat) {
|
switch (compressionFormat) {
|
||||||
case OMX_VIDEO_CodingMPEG4:
|
case OMX_VIDEO_CodingMPEG4:
|
||||||
{
|
{
|
||||||
@@ -911,7 +921,7 @@ status_t OMXCodec::setupAVCEncoderParameters() {
|
|||||||
CHECK_EQ(err, OK);
|
CHECK_EQ(err, OK);
|
||||||
|
|
||||||
bitrateType.eControlRate = OMX_Video_ControlRateVariable;
|
bitrateType.eControlRate = OMX_Video_ControlRateVariable;
|
||||||
bitrateType.nTargetBitrate = 1000000;
|
bitrateType.nTargetBitrate = 3000000;
|
||||||
|
|
||||||
err = mOMX->setParameter(
|
err = mOMX->setParameter(
|
||||||
mNode, OMX_IndexParamVideoBitrate,
|
mNode, OMX_IndexParamVideoBitrate,
|
||||||
@@ -2068,7 +2078,13 @@ void OMXCodec::fillOutputBuffer(BufferInfo *info) {
|
|||||||
|
|
||||||
CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
|
CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
|
||||||
status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
|
status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
|
||||||
CHECK_EQ(err, OK);
|
|
||||||
|
if (err != OK) {
|
||||||
|
CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
|
||||||
|
|
||||||
|
setState(ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
info->mOwnedByComponent = true;
|
info->mOwnedByComponent = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define __STDC_LIMIT_MACROS
|
#define __STDC_LIMIT_MACROS
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
#define LOG_TAG "TimedEventQueue"
|
#define LOG_TAG "TimedEventQueue"
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
|
|
||||||
@@ -169,6 +170,8 @@ void TimedEventQueue::cancelEvents(
|
|||||||
mQueueHeadChangedCondition.signal();
|
mQueueHeadChangedCondition.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGV("cancelling event %d", (*it).event->eventID());
|
||||||
|
|
||||||
(*it).event->setEventID(0);
|
(*it).event->setEventID(0);
|
||||||
it = mQueue.erase(it);
|
it = mQueue.erase(it);
|
||||||
|
|
||||||
@@ -229,14 +232,16 @@ void TimedEventQueue::threadEntry() {
|
|||||||
mQueueNotEmptyCondition.wait(mLock);
|
mQueueNotEmptyCondition.wait(mLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<QueueItem>::iterator it;
|
event_id eventID = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (mQueue.empty()) {
|
if (mQueue.empty()) {
|
||||||
// The only event in the queue could have been cancelled
|
// The only event in the queue could have been cancelled
|
||||||
// while we were waiting for its scheduled time.
|
// while we were waiting for its scheduled time.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
it = mQueue.begin();
|
|
||||||
|
List<QueueItem>::iterator it = mQueue.begin();
|
||||||
|
eventID = (*it).event->eventID();
|
||||||
|
|
||||||
now_us = getRealTimeUs();
|
now_us = getRealTimeUs();
|
||||||
int64_t when_us = (*it).realtime_us;
|
int64_t when_us = (*it).realtime_us;
|
||||||
@@ -276,19 +281,39 @@ void TimedEventQueue::threadEntry() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mQueue.empty()) {
|
// The event w/ this id may have been cancelled while we're
|
||||||
continue;
|
// waiting for its trigger-time, in that case
|
||||||
}
|
// removeEventFromQueue_l will return NULL.
|
||||||
|
// Otherwise, the QueueItem will be removed
|
||||||
event = (*it).event;
|
// from the queue and the referenced event returned.
|
||||||
event->setEventID(0);
|
event = removeEventFromQueue_l(eventID);
|
||||||
mQueue.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire event with the lock NOT held.
|
if (event != NULL) {
|
||||||
event->fire(this, now_us);
|
// Fire event with the lock NOT held.
|
||||||
|
event->fire(this, now_us);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(
|
||||||
|
event_id id) {
|
||||||
|
for (List<QueueItem>::iterator it = mQueue.begin();
|
||||||
|
it != mQueue.end(); ++it) {
|
||||||
|
if ((*it).event->eventID() == id) {
|
||||||
|
sp<Event> event = (*it).event;
|
||||||
|
event->setEventID(0);
|
||||||
|
|
||||||
|
mQueue.erase(it);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGW("Event %d was not found in the queue, already cancelled?", id);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ private:
|
|||||||
static void *ThreadWrapper(void *me);
|
static void *ThreadWrapper(void *me);
|
||||||
void threadEntry();
|
void threadEntry();
|
||||||
|
|
||||||
|
sp<Event> removeEventFromQueue_l(event_id id);
|
||||||
|
|
||||||
TimedEventQueue(const TimedEventQueue &);
|
TimedEventQueue(const TimedEventQueue &);
|
||||||
TimedEventQueue &operator=(const TimedEventQueue &);
|
TimedEventQueue &operator=(const TimedEventQueue &);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -264,6 +264,8 @@ status_t OMXNodeInstance::useBuffer(
|
|||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHECK_EQ(header->pAppPrivate, buffer_meta);
|
||||||
|
|
||||||
*buffer = header;
|
*buffer = header;
|
||||||
|
|
||||||
addActiveBuffer(portIndex, *buffer);
|
addActiveBuffer(portIndex, *buffer);
|
||||||
@@ -294,6 +296,8 @@ status_t OMXNodeInstance::allocateBuffer(
|
|||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHECK_EQ(header->pAppPrivate, buffer_meta);
|
||||||
|
|
||||||
*buffer = header;
|
*buffer = header;
|
||||||
*buffer_data = header->pBuffer;
|
*buffer_data = header->pBuffer;
|
||||||
|
|
||||||
@@ -325,6 +329,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup(
|
|||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHECK_EQ(header->pAppPrivate, buffer_meta);
|
||||||
|
|
||||||
*buffer = header;
|
*buffer = header;
|
||||||
|
|
||||||
addActiveBuffer(portIndex, *buffer);
|
addActiveBuffer(portIndex, *buffer);
|
||||||
|
|||||||
Reference in New Issue
Block a user