summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/stagefright/stagefright.cpp153
1 files changed, 111 insertions, 42 deletions
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index eb4b733..8b54871 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -31,6 +31,8 @@
#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ALooper.h>
#include "include/ARTSPController.h"
+#include "include/LiveSource.h"
+#include "include/NuCachedSource2.h"
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/JPEGSource.h>
@@ -285,19 +287,34 @@ struct DetectSyncSource : public MediaSource {
MediaBuffer **buffer, const ReadOptions *options);
private:
+ enum StreamType {
+ AVC,
+ MPEG4,
+ H263,
+ OTHER,
+ };
+
sp<MediaSource> mSource;
- bool mIsAVC;
+ StreamType mStreamType;
DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
};
DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
: mSource(source),
- mIsAVC(false) {
+ mStreamType(OTHER) {
const char *mime;
CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
- mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mStreamType = AVC;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+ mStreamType = MPEG4;
+ CHECK(!"sync frame detection not implemented yet for MPEG4");
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
+ mStreamType = H263;
+ CHECK(!"sync frame detection not implemented yet for H.263");
+ }
}
status_t DetectSyncSource::start(MetaData *params) {
@@ -336,10 +353,10 @@ status_t DetectSyncSource::read(
return err;
}
- if (mIsAVC && isIDRFrame(*buffer)) {
+ if (mStreamType == AVC && isIDRFrame(*buffer)) {
(*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
} else {
- (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, false);
+ (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
}
return OK;
@@ -347,19 +364,21 @@ status_t DetectSyncSource::read(
////////////////////////////////////////////////////////////////////////////////
-static void writeSourceToMP4(
- sp<MediaSource> &source, bool syncInfoPresent) {
- if (!syncInfoPresent) {
- source = new DetectSyncSource(source);
- }
-
+static void writeSourcesToMP4(
+ Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
sp<MPEG4Writer> writer =
new MPEG4Writer(gWriteMP4Filename.string());
// at most one minute.
writer->setMaxFileDuration(60000000ll);
- CHECK_EQ(writer->addSource(source), (status_t)OK);
+ for (size_t i = 0; i < sources.size(); ++i) {
+ sp<MediaSource> source = sources.editItemAt(i);
+
+ CHECK_EQ(writer->addSource(
+ syncInfoPresent ? source : new DetectSyncSource(source)),
+ (status_t)OK);
+ }
sp<MetaData> params = new MetaData;
params->setInt32(kKeyNotRealTime, true);
@@ -674,8 +693,10 @@ int main(int argc, char **argv) {
sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
- if ((strncasecmp(filename, "sine:", 5)
- && strncasecmp(filename, "rtsp://", 7)) && dataSource == NULL) {
+ if (strncasecmp(filename, "sine:", 5)
+ && strncasecmp(filename, "rtsp://", 7)
+ && strncasecmp(filename, "httplive://", 11)
+ && dataSource == NULL) {
fprintf(stderr, "Unable to create data source.\n");
return 1;
}
@@ -687,10 +708,14 @@ int main(int argc, char **argv) {
isJPEG = true;
}
+ Vector<sp<MediaSource> > mediaSources;
sp<MediaSource> mediaSource;
if (isJPEG) {
mediaSource = new JPEGSource(dataSource);
+ if (gWriteMP4) {
+ mediaSources.push(mediaSource);
+ }
} else if (!strncasecmp("sine:", filename, 5)) {
char *end;
long sampleRate = strtol(filename + 5, &end, 10);
@@ -699,6 +724,9 @@ int main(int argc, char **argv) {
sampleRate = 44100;
}
mediaSource = new SineSource(sampleRate, 1);
+ if (gWriteMP4) {
+ mediaSources.push(mediaSource);
+ }
} else {
sp<MediaExtractor> extractor;
@@ -718,6 +746,18 @@ int main(int argc, char **argv) {
extractor = rtspController.get();
syncInfoPresent = false;
+ } else if (!strncasecmp("httplive://", filename, 11)) {
+ String8 uri("http://");
+ uri.append(filename + 11);
+
+ dataSource = new LiveSource(uri.string());
+ dataSource = new NuCachedSource2(dataSource);
+
+ extractor =
+ MediaExtractor::Create(
+ dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+ syncInfoPresent = false;
} else {
extractor = MediaExtractor::Create(dataSource);
if (extractor == NULL) {
@@ -728,46 +768,75 @@ int main(int argc, char **argv) {
size_t numTracks = extractor->countTracks();
- sp<MetaData> meta;
- size_t i;
- for (i = 0; i < numTracks; ++i) {
- meta = extractor->getTrackMetaData(
- i, MediaExtractor::kIncludeExtensiveMetaData);
+ if (gWriteMP4) {
+ bool haveAudio = false;
+ bool haveVideo = false;
+ for (size_t i = 0; i < numTracks; ++i) {
+ sp<MediaSource> source = extractor->getTrack(i);
+
+ const char *mime;
+ CHECK(source->getFormat()->findCString(
+ kKeyMIMEType, &mime));
+
+ bool useTrack = false;
+ if (!haveAudio && !strncasecmp("audio/", mime, 6)) {
+ haveAudio = true;
+ useTrack = true;
+ } else if (!haveVideo && !strncasecmp("video/", mime, 6)) {
+ haveVideo = true;
+ useTrack = true;
+ }
- const char *mime;
- meta->findCString(kKeyMIMEType, &mime);
+ if (useTrack) {
+ mediaSources.push(source);
- if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
- break;
+ if (haveAudio && haveVideo) {
+ break;
+ }
+ }
}
+ } else {
+ sp<MetaData> meta;
+ size_t i;
+ for (i = 0; i < numTracks; ++i) {
+ meta = extractor->getTrackMetaData(
+ i, MediaExtractor::kIncludeExtensiveMetaData);
- if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
- break;
+ const char *mime;
+ meta->findCString(kKeyMIMEType, &mime);
+
+ if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
+ break;
+ }
+
+ if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
+ break;
+ }
+
+ meta = NULL;
}
- meta = NULL;
- }
+ if (meta == NULL) {
+ fprintf(stderr,
+ "No suitable %s track found. The '-a' option will "
+ "target audio tracks only, the default is to target "
+ "video tracks only.\n",
+ audioOnly ? "audio" : "video");
+ return -1;
+ }
- if (meta == NULL) {
- fprintf(stderr,
- "No suitable %s track found. The '-a' option will "
- "target audio tracks only, the default is to target "
- "video tracks only.\n",
- audioOnly ? "audio" : "video");
- return -1;
- }
+ int64_t thumbTimeUs;
+ if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
+ printf("thumbnailTime: %lld us (%.2f secs)\n",
+ thumbTimeUs, thumbTimeUs / 1E6);
+ }
- int64_t thumbTimeUs;
- if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
- printf("thumbnailTime: %lld us (%.2f secs)\n",
- thumbTimeUs, thumbTimeUs / 1E6);
+ mediaSource = extractor->getTrack(i);
}
-
- mediaSource = extractor->getTrack(i);
}
if (gWriteMP4) {
- writeSourceToMP4(mediaSource, syncInfoPresent);
+ writeSourcesToMP4(mediaSources, syncInfoPresent);
} else if (seekTest) {
performSeekTest(mediaSource);
} else {