Loading cmds/stagefright/stagefright.cpp +203 −41 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "stagefright" #include <media/stagefright/foundation/ADebug.h> #include <sys/time.h> #include <stdlib.h> Loading @@ -27,10 +31,11 @@ #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> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaExtractor.h> Loading @@ -43,6 +48,8 @@ #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/MPEG4Writer.h> #include <fcntl.h> using namespace android; static long gNumRepetitions; Loading Loading @@ -120,7 +127,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { bool shouldSeek = false; if (err == INFO_FORMAT_CHANGED) { CHECK_EQ(buffer, NULL); CHECK(buffer == NULL); printf("format changed.\n"); continue; Loading Loading @@ -206,7 +213,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { options.clearSeekTo(); if (err != OK) { CHECK_EQ(buffer, NULL); CHECK(buffer == NULL); if (err == INFO_FORMAT_CHANGED) { printf("format changed.\n"); Loading Loading @@ -267,14 +274,115 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { } } static void writeSourceToMP4(const sp<MediaSource> &source) { //////////////////////////////////////////////////////////////////////////////// struct DetectSyncSource : public MediaSource { DetectSyncSource(const sp<MediaSource> &source); virtual status_t start(MetaData *params = NULL); virtual status_t stop(); virtual sp<MetaData> getFormat(); virtual status_t read( MediaBuffer **buffer, const ReadOptions *options); private: enum StreamType { AVC, MPEG4, H263, OTHER, }; sp<MediaSource> mSource; StreamType mStreamType; DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource); }; DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source) : mSource(source), mStreamType(OTHER) { const char *mime; CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 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) { return mSource->start(params); } status_t DetectSyncSource::stop() { return mSource->stop(); } sp<MetaData> DetectSyncSource::getFormat() { return mSource->getFormat(); } static bool isIDRFrame(MediaBuffer *buffer) { const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); size_t size = buffer->range_length(); for (size_t i = 0; i + 3 < size; ++i) { if (!memcmp("\x00\x00\x01", &data[i], 3)) { uint8_t nalType = data[i + 3] & 0x1f; if (nalType == 5) { return true; } } } return false; } status_t DetectSyncSource::read( MediaBuffer **buffer, const ReadOptions *options) { status_t err = mSource->read(buffer, options); if (err != OK) { return err; } if (mStreamType == AVC && isIDRFrame(*buffer)) { (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true); } else { (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true); } return OK; } //////////////////////////////////////////////////////////////////////////////// static void writeSourcesToMP4( Vector<sp<MediaSource> > &sources, bool syncInfoPresent) { sp<MPEG4Writer> writer = new MPEG4Writer(gWriteMP4Filename.string()); CHECK_EQ(writer->addSource(source), OK); // at most one minute. writer->setMaxFileDuration(60000000ll); 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; CHECK_EQ(writer->start(), OK); params->setInt32(kKeyNotRealTime, true); CHECK_EQ(writer->start(params.get()), (status_t)OK); while (!writer->reachedEOS()) { usleep(100000); Loading @@ -283,7 +391,7 @@ static void writeSourceToMP4(const sp<MediaSource> &source) { } static void performSeekTest(const sp<MediaSource> &source) { CHECK_EQ(OK, source->start()); CHECK_EQ((status_t)OK, source->start()); int64_t durationUs; CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs)); Loading Loading @@ -335,7 +443,7 @@ static void performSeekTest(const sp<MediaSource> &source) { } } CHECK_EQ(OK, source->stop()); CHECK_EQ((status_t)OK, source->stop()); } static void usage(const char *me) { Loading Loading @@ -481,10 +589,10 @@ int main(int argc, char **argv) { for (int k = 0; k < argc; ++k) { const char *filename = argv[k]; CHECK_EQ(retriever->setDataSource(filename), OK); CHECK_EQ(retriever->setDataSource(filename), (status_t)OK); CHECK_EQ(retriever->setMode( METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL), OK); (status_t)OK); sp<IMemory> mem = retriever->captureFrame(); Loading Loading @@ -530,7 +638,7 @@ int main(int argc, char **argv) { Vector<CodecCapabilities> results; CHECK_EQ(QueryCodecs(omx, kMimeTypes[k], true, // queryDecoders &results), OK); &results), (status_t)OK); for (size_t i = 0; i < results.size(); ++i) { printf(" decoder '%s' supports ", Loading Loading @@ -579,12 +687,16 @@ int main(int argc, char **argv) { status_t err = client.connect(); for (int k = 0; k < argc; ++k) { bool syncInfoPresent = true; const char *filename = argv[k]; 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; } Loading @@ -596,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); Loading @@ -608,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; Loading @@ -625,6 +744,20 @@ 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) { Loading @@ -635,6 +768,34 @@ int main(int argc, char **argv) { size_t numTracks = extractor->countTracks(); 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; } if (useTrack) { mediaSources.push(source); if (haveAudio && haveVideo) { break; } } } } else { sp<MetaData> meta; size_t i; for (i = 0; i < numTracks; ++i) { Loading Loading @@ -672,9 +833,10 @@ int main(int argc, char **argv) { mediaSource = extractor->getTrack(i); } } if (gWriteMP4) { writeSourceToMP4(mediaSource); writeSourcesToMP4(mediaSources, syncInfoPresent); } else if (seekTest) { performSeekTest(mediaSource); } else { Loading media/libstagefright/MPEG4Writer.cpp +9 −1 Original line number Diff line number Diff line Loading @@ -2111,7 +2111,15 @@ void MPEG4Writer::Track::writeTrackHeader( mOwner->endBox(); // d263 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { CHECK(mCodecSpecificData); CHECK(mCodecSpecificDataSize > 0); CHECK(mCodecSpecificDataSize >= 5); // Patch avcc's lengthSize field to match the number // of bytes we use to indicate the size of a nal unit. uint8_t *ptr = (uint8_t *)mCodecSpecificData; ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); mOwner->beginBox("avcC"); mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); mOwner->endBox(); // avcC Loading media/libstagefright/OMXCodec.cpp +13 −6 Original line number Diff line number Diff line Loading @@ -980,7 +980,10 @@ status_t OMXCodec::setupErrorCorrectionParameters() { status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoErrorCorrection, &errorCorrectionType, sizeof(errorCorrectionType)); CHECK_EQ(err, OK); if (err != OK) { LOGW("Error correction param query is not supported"); return OK; // Optional feature. Ignore this failure } errorCorrectionType.bEnableHEC = OMX_FALSE; errorCorrectionType.bEnableResync = OMX_TRUE; Loading @@ -991,7 +994,11 @@ status_t OMXCodec::setupErrorCorrectionParameters() { err = mOMX->setParameter( mNode, OMX_IndexParamVideoErrorCorrection, &errorCorrectionType, sizeof(errorCorrectionType)); CHECK_EQ(err, OK); if (err != OK) { LOGW("Error correction param configuration is not supported"); } // Optional feature. Ignore the failure. return OK; } Loading Loading @@ -1089,8 +1096,8 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { // Check profile and level parameters CodecProfileLevel defaultProfileLevel, profileLevel; defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline; defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45; defaultProfileLevel.mProfile = h263type.eProfile; defaultProfileLevel.mLevel = h263type.eLevel; err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); if (err != OK) return err; h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile); Loading Loading @@ -1146,8 +1153,8 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { // Check profile and level parameters CodecProfileLevel defaultProfileLevel, profileLevel; defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple; defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2; defaultProfileLevel.mProfile = mpeg4type.eProfile; defaultProfileLevel.mLevel = mpeg4type.eLevel; err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); if (err != OK) return err; mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile); Loading services/audioflinger/AudioFlinger.cpp +49 −40 Original line number Diff line number Diff line Loading @@ -4653,9 +4653,6 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } { Mutex::Autolock _l(mLock); // check audio settings permission for global effects if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) { lStatus = PERMISSION_DENIED; Loading @@ -4677,6 +4674,24 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } if (output == 0) { if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) { // output must be specified by AudioPolicyManager when using session // AudioSystem::SESSION_OUTPUT_STAGE lStatus = BAD_VALUE; goto Exit; } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) { // if the output returned by getOutputForEffect() is removed before we lock the // mutex below, the call to checkPlaybackThread_l(output) below will detect it // and we will exit safely output = AudioSystem::getOutputForEffect(&desc); } } { Mutex::Autolock _l(mLock); if (!EffectIsNullUuid(&pDesc->uuid)) { // if uuid is specified, request effect descriptor lStatus = EffectGetDescriptor(&pDesc->uuid, &desc); Loading Loading @@ -4744,17 +4759,9 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, // If output is not specified try to find a matching audio session ID in one of the // output threads. // TODO: allow attachment of effect to inputs // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX // because of code checking output when entering the function. if (output == 0) { if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) { // output must be specified by AudioPolicyManager when using session // AudioSystem::SESSION_OUTPUT_STAGE lStatus = BAD_VALUE; goto Exit; } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) { output = AudioSystem::getOutputForEffect(&desc); LOGV("createEffect() got output %d for effect %s", output, desc.name); } else { // look for the thread where the specified audio session is present for (size_t i = 0; i < mPlaybackThreads.size(); i++) { if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) { Loading @@ -4769,7 +4776,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, output = mPlaybackThreads.keyAt(0); } } } LOGV("createEffect() got output %d for effect %s", output, desc.name); PlaybackThread *thread = checkPlaybackThread_l(output); if (thread == NULL) { LOGE("createEffect() unknown output thread"); Loading @@ -4777,6 +4784,8 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } // TODO: allow attachment of effect to inputs wclient = mClients.valueFor(pid); if (wclient != NULL) { Loading Loading
cmds/stagefright/stagefright.cpp +203 −41 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "stagefright" #include <media/stagefright/foundation/ADebug.h> #include <sys/time.h> #include <stdlib.h> Loading @@ -27,10 +31,11 @@ #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> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaExtractor.h> Loading @@ -43,6 +48,8 @@ #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/MPEG4Writer.h> #include <fcntl.h> using namespace android; static long gNumRepetitions; Loading Loading @@ -120,7 +127,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { bool shouldSeek = false; if (err == INFO_FORMAT_CHANGED) { CHECK_EQ(buffer, NULL); CHECK(buffer == NULL); printf("format changed.\n"); continue; Loading Loading @@ -206,7 +213,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { options.clearSeekTo(); if (err != OK) { CHECK_EQ(buffer, NULL); CHECK(buffer == NULL); if (err == INFO_FORMAT_CHANGED) { printf("format changed.\n"); Loading Loading @@ -267,14 +274,115 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { } } static void writeSourceToMP4(const sp<MediaSource> &source) { //////////////////////////////////////////////////////////////////////////////// struct DetectSyncSource : public MediaSource { DetectSyncSource(const sp<MediaSource> &source); virtual status_t start(MetaData *params = NULL); virtual status_t stop(); virtual sp<MetaData> getFormat(); virtual status_t read( MediaBuffer **buffer, const ReadOptions *options); private: enum StreamType { AVC, MPEG4, H263, OTHER, }; sp<MediaSource> mSource; StreamType mStreamType; DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource); }; DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source) : mSource(source), mStreamType(OTHER) { const char *mime; CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 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) { return mSource->start(params); } status_t DetectSyncSource::stop() { return mSource->stop(); } sp<MetaData> DetectSyncSource::getFormat() { return mSource->getFormat(); } static bool isIDRFrame(MediaBuffer *buffer) { const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); size_t size = buffer->range_length(); for (size_t i = 0; i + 3 < size; ++i) { if (!memcmp("\x00\x00\x01", &data[i], 3)) { uint8_t nalType = data[i + 3] & 0x1f; if (nalType == 5) { return true; } } } return false; } status_t DetectSyncSource::read( MediaBuffer **buffer, const ReadOptions *options) { status_t err = mSource->read(buffer, options); if (err != OK) { return err; } if (mStreamType == AVC && isIDRFrame(*buffer)) { (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true); } else { (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true); } return OK; } //////////////////////////////////////////////////////////////////////////////// static void writeSourcesToMP4( Vector<sp<MediaSource> > &sources, bool syncInfoPresent) { sp<MPEG4Writer> writer = new MPEG4Writer(gWriteMP4Filename.string()); CHECK_EQ(writer->addSource(source), OK); // at most one minute. writer->setMaxFileDuration(60000000ll); 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; CHECK_EQ(writer->start(), OK); params->setInt32(kKeyNotRealTime, true); CHECK_EQ(writer->start(params.get()), (status_t)OK); while (!writer->reachedEOS()) { usleep(100000); Loading @@ -283,7 +391,7 @@ static void writeSourceToMP4(const sp<MediaSource> &source) { } static void performSeekTest(const sp<MediaSource> &source) { CHECK_EQ(OK, source->start()); CHECK_EQ((status_t)OK, source->start()); int64_t durationUs; CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs)); Loading Loading @@ -335,7 +443,7 @@ static void performSeekTest(const sp<MediaSource> &source) { } } CHECK_EQ(OK, source->stop()); CHECK_EQ((status_t)OK, source->stop()); } static void usage(const char *me) { Loading Loading @@ -481,10 +589,10 @@ int main(int argc, char **argv) { for (int k = 0; k < argc; ++k) { const char *filename = argv[k]; CHECK_EQ(retriever->setDataSource(filename), OK); CHECK_EQ(retriever->setDataSource(filename), (status_t)OK); CHECK_EQ(retriever->setMode( METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL), OK); (status_t)OK); sp<IMemory> mem = retriever->captureFrame(); Loading Loading @@ -530,7 +638,7 @@ int main(int argc, char **argv) { Vector<CodecCapabilities> results; CHECK_EQ(QueryCodecs(omx, kMimeTypes[k], true, // queryDecoders &results), OK); &results), (status_t)OK); for (size_t i = 0; i < results.size(); ++i) { printf(" decoder '%s' supports ", Loading Loading @@ -579,12 +687,16 @@ int main(int argc, char **argv) { status_t err = client.connect(); for (int k = 0; k < argc; ++k) { bool syncInfoPresent = true; const char *filename = argv[k]; 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; } Loading @@ -596,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); Loading @@ -608,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; Loading @@ -625,6 +744,20 @@ 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) { Loading @@ -635,6 +768,34 @@ int main(int argc, char **argv) { size_t numTracks = extractor->countTracks(); 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; } if (useTrack) { mediaSources.push(source); if (haveAudio && haveVideo) { break; } } } } else { sp<MetaData> meta; size_t i; for (i = 0; i < numTracks; ++i) { Loading Loading @@ -672,9 +833,10 @@ int main(int argc, char **argv) { mediaSource = extractor->getTrack(i); } } if (gWriteMP4) { writeSourceToMP4(mediaSource); writeSourcesToMP4(mediaSources, syncInfoPresent); } else if (seekTest) { performSeekTest(mediaSource); } else { Loading
media/libstagefright/MPEG4Writer.cpp +9 −1 Original line number Diff line number Diff line Loading @@ -2111,7 +2111,15 @@ void MPEG4Writer::Track::writeTrackHeader( mOwner->endBox(); // d263 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { CHECK(mCodecSpecificData); CHECK(mCodecSpecificDataSize > 0); CHECK(mCodecSpecificDataSize >= 5); // Patch avcc's lengthSize field to match the number // of bytes we use to indicate the size of a nal unit. uint8_t *ptr = (uint8_t *)mCodecSpecificData; ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); mOwner->beginBox("avcC"); mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); mOwner->endBox(); // avcC Loading
media/libstagefright/OMXCodec.cpp +13 −6 Original line number Diff line number Diff line Loading @@ -980,7 +980,10 @@ status_t OMXCodec::setupErrorCorrectionParameters() { status_t err = mOMX->getParameter( mNode, OMX_IndexParamVideoErrorCorrection, &errorCorrectionType, sizeof(errorCorrectionType)); CHECK_EQ(err, OK); if (err != OK) { LOGW("Error correction param query is not supported"); return OK; // Optional feature. Ignore this failure } errorCorrectionType.bEnableHEC = OMX_FALSE; errorCorrectionType.bEnableResync = OMX_TRUE; Loading @@ -991,7 +994,11 @@ status_t OMXCodec::setupErrorCorrectionParameters() { err = mOMX->setParameter( mNode, OMX_IndexParamVideoErrorCorrection, &errorCorrectionType, sizeof(errorCorrectionType)); CHECK_EQ(err, OK); if (err != OK) { LOGW("Error correction param configuration is not supported"); } // Optional feature. Ignore the failure. return OK; } Loading Loading @@ -1089,8 +1096,8 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { // Check profile and level parameters CodecProfileLevel defaultProfileLevel, profileLevel; defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline; defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45; defaultProfileLevel.mProfile = h263type.eProfile; defaultProfileLevel.mLevel = h263type.eLevel; err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); if (err != OK) return err; h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile); Loading Loading @@ -1146,8 +1153,8 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { // Check profile and level parameters CodecProfileLevel defaultProfileLevel, profileLevel; defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple; defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2; defaultProfileLevel.mProfile = mpeg4type.eProfile; defaultProfileLevel.mLevel = mpeg4type.eLevel; err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel); if (err != OK) return err; mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile); Loading
services/audioflinger/AudioFlinger.cpp +49 −40 Original line number Diff line number Diff line Loading @@ -4653,9 +4653,6 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } { Mutex::Autolock _l(mLock); // check audio settings permission for global effects if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) { lStatus = PERMISSION_DENIED; Loading @@ -4677,6 +4674,24 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } if (output == 0) { if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) { // output must be specified by AudioPolicyManager when using session // AudioSystem::SESSION_OUTPUT_STAGE lStatus = BAD_VALUE; goto Exit; } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) { // if the output returned by getOutputForEffect() is removed before we lock the // mutex below, the call to checkPlaybackThread_l(output) below will detect it // and we will exit safely output = AudioSystem::getOutputForEffect(&desc); } } { Mutex::Autolock _l(mLock); if (!EffectIsNullUuid(&pDesc->uuid)) { // if uuid is specified, request effect descriptor lStatus = EffectGetDescriptor(&pDesc->uuid, &desc); Loading Loading @@ -4744,17 +4759,9 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, // If output is not specified try to find a matching audio session ID in one of the // output threads. // TODO: allow attachment of effect to inputs // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX // because of code checking output when entering the function. if (output == 0) { if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) { // output must be specified by AudioPolicyManager when using session // AudioSystem::SESSION_OUTPUT_STAGE lStatus = BAD_VALUE; goto Exit; } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) { output = AudioSystem::getOutputForEffect(&desc); LOGV("createEffect() got output %d for effect %s", output, desc.name); } else { // look for the thread where the specified audio session is present for (size_t i = 0; i < mPlaybackThreads.size(); i++) { if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) { Loading @@ -4769,7 +4776,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, output = mPlaybackThreads.keyAt(0); } } } LOGV("createEffect() got output %d for effect %s", output, desc.name); PlaybackThread *thread = checkPlaybackThread_l(output); if (thread == NULL) { LOGE("createEffect() unknown output thread"); Loading @@ -4777,6 +4784,8 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } // TODO: allow attachment of effect to inputs wclient = mClients.valueFor(pid); if (wclient != NULL) { Loading