From 79e2b622702fb148ccff12d6f38643466555c4eb Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Fri, 16 May 2014 08:07:28 -0700 Subject: Add docs, releaseOutputBufferAtTime, seekTo. Change-Id: Iadd231b63e75b7937c13d2ebfef47aedeaeef5a1 --- include/ndk/NdkMediaCodec.h | 58 ++++++++++++++++++++++++++++++++++++----- include/ndk/NdkMediaCrypto.h | 1 + include/ndk/NdkMediaExtractor.h | 11 +++++++- include/ndk/NdkMediaMuxer.h | 45 +++++++++++++++++++++++++++++++- media/ndk/NdkMediaCodec.cpp | 15 ++++++++--- media/ndk/NdkMediaExtractor.cpp | 16 +++++++++++- 6 files changed, 133 insertions(+), 13 deletions(-) diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h index dd869f6..2f000d7 100644 --- a/include/ndk/NdkMediaCodec.h +++ b/include/ndk/NdkMediaCodec.h @@ -146,10 +146,22 @@ ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *inf AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*); /** - * Release and optionally render the specified buffer. + * If you are done with a buffer, use this call to return the buffer to + * the codec. If you previously specified a surface when configuring this + * video decoder you can optionally render the buffer. */ media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec*, size_t idx, bool render); +/** + * If you are done with a buffer, use this call to update its surface timestamp + * and return it to the codec to render it on the output surface. If you + * have not specified an output surface when configuring this video codec, + * this call will simply return the buffer to the codec. + * + * For more details, see the Java documentation for MediaCodec.releaseOutputBuffer. + */ +media_status_t AMediaCodec_releaseOutputBufferAtTime( + AMediaCodec *mData, size_t idx, int64_t timestampNs); typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata); @@ -163,20 +175,30 @@ media_status_t AMediaCodec_setNotificationCallback( AMediaCodec*, OnCodecEvent callback, void *userdata); -enum { +typedef enum { AMEDIACODECRYPTOINFO_MODE_CLEAR = 0, AMEDIACODECRYPTOINFO_MODE_AES_CTR = 1 -}; +} cryptoinfo_mode_t; /** - * create an AMediaCodecCryptoInfo from scratch. Use this if you need to use custom + * Create an AMediaCodecCryptoInfo from scratch. Use this if you need to use custom * crypto info, rather than one obtained from AMediaExtractor. + * + * AMediaCodecCryptoInfo describes the structure of an (at least + * partially) encrypted input sample. + * A buffer's data is considered to be partitioned into "subsamples", + * each subsample starts with a (potentially empty) run of plain, + * unencrypted bytes followed by a (also potentially empty) run of + * encrypted bytes. + * numBytesOfClearData can be null to indicate that all data is encrypted. + * This information encapsulates per-sample metadata as outlined in + * ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base media file format files". */ AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new( int numsubsamples, uint8_t key[16], uint8_t iv[16], - uint32_t mode, + cryptoinfo_mode_t mode, size_t *clearbytes, size_t *encryptedbytes); @@ -186,11 +208,35 @@ AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new( */ media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo*); +/** + * The number of subsamples that make up the buffer's contents. + */ size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo*); + +/** + * A 16-byte opaque key + */ media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo*, uint8_t *dst); + +/** + * A 16-byte initialization vector + */ media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo*, uint8_t *dst); -uint32_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo*); + +/** + * The type of encryption that has been applied, + * one of AMEDIACODECRYPTOINFO_MODE_CLEAR or AMEDIACODECRYPTOINFO_MODE_AES_CTR. + */ +cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo*); + +/** + * The number of leading unencrypted bytes in each subsample. + */ media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo*, size_t *dst); + +/** + * The number of trailing encrypted bytes in each subsample. + */ media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo*, size_t *dst); #ifdef __cplusplus diff --git a/include/ndk/NdkMediaCrypto.h b/include/ndk/NdkMediaCrypto.h index 83eaad2..90374c5 100644 --- a/include/ndk/NdkMediaCrypto.h +++ b/include/ndk/NdkMediaCrypto.h @@ -29,6 +29,7 @@ #define _NDK_MEDIA_CRYPTO_H #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/ndk/NdkMediaExtractor.h b/include/ndk/NdkMediaExtractor.h index 2ba69fb..5a319d7 100644 --- a/include/ndk/NdkMediaExtractor.h +++ b/include/ndk/NdkMediaExtractor.h @@ -114,6 +114,16 @@ int64_t AMediaExtractor_getSampletime(AMediaExtractor*); */ bool AMediaExtractor_advance(AMediaExtractor*); +typedef enum { + AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC, + AMEDIAEXTRACTOR_SEEK_NEXT_SYNC, + AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC +} SeekMode; + +/** + * + */ +media_status_t AMediaExtractor_seekTo(AMediaExtractor*, int64_t seekPosUs, SeekMode mode); /** * mapping of crypto scheme uuid to the scheme specific data for that scheme @@ -146,7 +156,6 @@ enum { AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED = 2, }; - #ifdef __cplusplus } // extern "C" #endif diff --git a/include/ndk/NdkMediaMuxer.h b/include/ndk/NdkMediaMuxer.h index db183e9..1ddc51d 100644 --- a/include/ndk/NdkMediaMuxer.h +++ b/include/ndk/NdkMediaMuxer.h @@ -56,16 +56,59 @@ AMediaMuxer* AMediaMuxer_new(int fd, OutputFormat format); */ media_status_t AMediaMuxer_delete(AMediaMuxer*); -media_status_t AMediaMuxer_setLocation(AMediaMuxer*, float latitude, float longtitude); +/** + * Set and store the geodata (latitude and longitude) in the output file. + * This method should be called before AMediaMuxer_start. The geodata is stored + * in udta box if the output format is AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4, and is + * ignored for other output formats. + * The geodata is stored according to ISO-6709 standard. + * + * Both values are specified in degrees. + * Latitude must be in the range [-90, 90]. + * Longitude must be in the range [-180, 180]. + */ +media_status_t AMediaMuxer_setLocation(AMediaMuxer*, float latitude, float longitude); +/** + * Sets the orientation hint for output video playback. + * This method should be called before AMediaMuxer_start. Calling this + * method will not rotate the video frame when muxer is generating the file, + * but add a composition matrix containing the rotation angle in the output + * video if the output format is AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4, so that a + * video player can choose the proper orientation for playback. + * Note that some video players may choose to ignore the composition matrix + * during playback. + * The angle is specified in degrees, clockwise. + * The supported angles are 0, 90, 180, and 270 degrees. + */ media_status_t AMediaMuxer_setOrientationHint(AMediaMuxer*, int degrees); +/** + * Adds a track with the specified format. + * Returns the index of the new track or a negative value in case of failure, + * which can be interpreted as a media_status_t. + */ ssize_t AMediaMuxer_addTrack(AMediaMuxer*, const AMediaFormat* format); +/** + * Start the muxer. Should be called after AMediaMuxer_addTrack and + * before AMediaMuxer_writeSampleData. + */ media_status_t AMediaMuxer_start(AMediaMuxer*); +/** + * Stops the muxer. + * Once the muxer stops, it can not be restarted. + */ media_status_t AMediaMuxer_stop(AMediaMuxer*); +/** + * Writes an encoded sample into the muxer. + * The application needs to make sure that the samples are written into + * the right tracks. Also, it needs to make sure the samples for each track + * are written in chronological order (e.g. in the order they are provided + * by the encoder.) + */ media_status_t AMediaMuxer_writeSampleData(AMediaMuxer *muxer, size_t trackIdx, const uint8_t *data, const AMediaCodecBufferInfo &info); diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp index 9e2aa67..bd2541f 100644 --- a/media/ndk/NdkMediaCodec.cpp +++ b/media/ndk/NdkMediaCodec.cpp @@ -341,6 +341,13 @@ media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, b } EXPORT +media_status_t AMediaCodec_releaseOutputBufferAtTime( + AMediaCodec *mData, size_t idx, int64_t timestampNs) { + ALOGV("render @ %lld", timestampNs); + return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs)); +} + +EXPORT media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback, void *userdata) { mData->mCallback = callback; mData->mCallbackUserData = userdata; @@ -351,7 +358,7 @@ typedef struct AMediaCodecCryptoInfo { int numsubsamples; uint8_t key[16]; uint8_t iv[16]; - uint32_t mode; + cryptoinfo_mode_t mode; size_t *clearbytes; size_t *encryptedbytes; } AMediaCodecCryptoInfo; @@ -396,7 +403,7 @@ AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new( int numsubsamples, uint8_t key[16], uint8_t iv[16], - uint32_t mode, + cryptoinfo_mode_t mode, size_t *clearbytes, size_t *encryptedbytes) { @@ -459,9 +466,9 @@ media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *d } EXPORT -uint32_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) { +cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) { if (!ci) { - return AMEDIA_ERROR_INVALID_OBJECT; + return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT; } return ci->mode; } diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp index 563358f..b0a9590 100644 --- a/media/ndk/NdkMediaExtractor.cpp +++ b/media/ndk/NdkMediaExtractor.cpp @@ -150,6 +150,20 @@ bool AMediaExtractor_advance(AMediaExtractor *mData) { } EXPORT +media_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) { + android::MediaSource::ReadOptions::SeekMode sfmode; + if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) { + sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; + } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) { + sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC; + } else { + sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC; + } + + return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode)); +} + +EXPORT ssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) { //ALOGV("readSampleData"); sp tmp = new ABuffer(buffer, capacity); @@ -331,7 +345,7 @@ AMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) numSubSamples, (uint8_t*) key, (uint8_t*) iv, - mode, + (cryptoinfo_mode_t) mode, (size_t*) cleardata, (size_t*) crypteddata); } -- cgit v1.1