diff --git a/aaudio/AAudio.odin b/aaudio/AAudio.odin new file mode 100644 index 0000000..ede6568 --- /dev/null +++ b/aaudio/AAudio.odin @@ -0,0 +1,1750 @@ +//+build android +package aaudio + +foreign import aaudio "system:aaudio" + +/** + * This is used to represent a value that has not been specified. + * For example, an application could use {@link #AAUDIO_UNSPECIFIED} to indicate + * that it did not care what the specific value of a parameter was + * and would accept whatever it was given. + */ +AAUDIO_UNSPECIFIED :: 0 +AAUDIO_SYSTEM_USAGE_OFFSET :: 1000 + +// TODO: doesn't belong here. move to sys/android or something. +clockid_t :: i32 + +AAudioDirection :: enum i32 { + /** + * Audio data will travel out of the device, for example through a speaker. + */ + OUTPUT, + + + /** + * Audio data will travel into the device, for example from a microphone. + */ + INPUT +} + +AAudioFormat :: enum i32 { + INVALID = -1, + UNSPECIFIED = 0, + + /** + * This format uses the int16_t data type. + * The maximum range of the data is -32768 (0x8000) to 32767 (0x7FFF). + */ + PCM_I16, + + /** + * This format uses the float data type. + * The nominal range of the data is [-1.0f, 1.0f). + * Values outside that range may be clipped. + * + * See also the float Data in + * + * write(float[], int, int, int). + */ + PCM_FLOAT, + + /** + * This format uses 24-bit samples packed into 3 bytes. + * The bytes are in little-endian order, so the least significant byte + * comes first in the byte array. + * + * The maximum range of the data is -8388608 (0x800000) + * to 8388607 (0x7FFFFF). + * + * Note that the lower precision bits may be ignored by the device. + * + * Available since API level 31. + */ + PCM_I24_PACKED, + + /** + * This format uses 32-bit samples stored in an int32_t data type. + * The maximum range of the data is -2147483648 (0x80000000) + * to 2147483647 (0x7FFFFFFF). + * + * Note that the lower precision bits may be ignored by the device. + * + * Available since API level 31. + */ + PCM_I32 +} + +/** + * These result codes are returned from AAudio functions to indicate success or failure. + * Note that error return codes may change in the future so applications should generally + * not rely on specific return codes. + */ +AAudioResult :: enum i32 { + /** + * The call was successful. + */ + OK, + ERROR_BASE = -900, + + /** + * The audio device was disconnected. This could occur, for example, when headphones + * are plugged in or unplugged. The stream cannot be used after the device is disconnected. + * Applications should stop and close the stream. + * If this error is received in an error callback then another thread should be + * used to stop and close the stream. + */ + ERROR_DISCONNECTED, + + /** + * An invalid parameter was passed to AAudio. + */ + ERROR_ILLEGAL_ARGUMENT, + // reserved + ERROR_INTERNAL = ERROR_ILLEGAL_ARGUMENT + 2, + + /** + * The requested operation is not appropriate for the current state of AAudio. + */ + ERROR_INVALID_STATE, + // reserved + // reserved + /* The server rejected the handle used to identify the stream. + */ + ERROR_INVALID_HANDLE = ERROR_INVALID_STATE + 3, + // reserved + + /** + * The function is not implemented for this stream. + */ + ERROR_UNIMPLEMENTED = ERROR_INVALID_HANDLE + 2, + + /** + * A resource or information is unavailable. + * This could occur when an application tries to open too many streams, + * or a timestamp is not available. + */ + ERROR_UNAVAILABLE, + ERROR_NO_FREE_HANDLES, + + /** + * Memory could not be allocated. + */ + ERROR_NO_MEMORY, + + /** + * A NULL pointer was passed to AAudio. + * Or a NULL pointer was detected internally. + */ + ERROR_NULL, + + /** + * An operation took longer than expected. + */ + ERROR_TIMEOUT, + ERROR_WOULD_BLOCK, + + /** + * The requested data format is not supported. + */ + ERROR_INVALID_FORMAT, + + /** + * A requested was out of range. + */ + ERROR_OUT_OF_RANGE, + + /** + * The audio service was not available. + */ + ERROR_NO_SERVICE, + + /** + * The requested sample rate was not supported. + */ + ERROR_INVALID_RATE +} + +/** + * AAudio Stream states, for details, refer to + * Using an Audio Stream + */ +AAudioStreamState :: enum i32 { + /** + * The stream is created but not initialized yet. + */ + UNINITIALIZED = 0, + /** + * The stream is in an unrecognized state. + */ + UNKNOWN, + + /** + * The stream is open and ready to use. + */ + OPEN, + /** + * The stream is just starting up. + */ + STARTING, + /** + * The stream has started. + */ + STARTED, + /** + * The stream is pausing. + */ + PAUSING, + /** + * The stream has paused, could be restarted or flushed. + */ + PAUSED, + /** + * The stream is being flushed. + */ + FLUSHING, + /** + * The stream is flushed, ready to be restarted. + */ + FLUSHED, + /** + * The stream is stopping. + */ + STOPPING, + /** + * The stream has been stopped. + */ + STOPPED, + /** + * The stream is closing. + */ + CLOSING, + /** + * The stream has been closed. + */ + CLOSED, + /** + * The stream is disconnected from audio device. + */ + DISCONNECTED +} + + +AAudioSharingMode :: enum i32 { + /** + * This will be the only stream using a particular source or sink. + * This mode will provide the lowest possible latency. + * You should close EXCLUSIVE streams immediately when you are not using them. + */ + EXCLUSIVE, + /** + * Multiple applications will be mixed by the AAudio Server. + * This will have higher latency than the EXCLUSIVE mode. + */ + SHARED +} + + +AAudioPerformanceMode :: enum i32 { + /** + * No particular performance needs. Default. + */ + NONE = 10, + + /** + * Extending battery life is more important than low latency. + * + * This mode is not supported in input streams. + * For input, mode NONE will be used if this is requested. + */ + POWER_SAVING, + + /** + * Reducing latency is more important than battery life. + */ + LOW_LATENCY +} + +/** + * The USAGE attribute expresses "why" you are playing a sound, what is this sound used for. + * This information is used by certain platforms or routing policies + * to make more refined volume or routing decisions. + * + * Note that these match the equivalent values in + * AudioAttributes + * in the Android Java API. + * + * Added in API level 28. + */ +AAudioUsage :: enum i32 { + /** + * Use this for streaming media, music performance, video, podcasts, etcetera. + */ + MEDIA = 1, + + /** + * Use this for voice over IP, telephony, etcetera. + */ + VOICE_COMMUNICATION = 2, + + /** + * Use this for sounds associated with telephony such as busy tones, DTMF, etcetera. + */ + VOICE_COMMUNICATION_SIGNALLING = 3, + + /** + * Use this to demand the users attention. + */ + ALARM = 4, + + /** + * Use this for notifying the user when a message has arrived or some + * other background event has occured. + */ + NOTIFICATION = 5, + + /** + * Use this when the phone rings. + */ + NOTIFICATION_RINGTONE = 6, + + /** + * Use this to attract the users attention when, for example, the battery is low. + */ + NOTIFICATION_EVENT = 10, + + /** + * Use this for screen readers, etcetera. + */ + ASSISTANCE_ACCESSIBILITY = 11, + + /** + * Use this for driving or navigation directions. + */ + ASSISTANCE_NAVIGATION_GUIDANCE = 12, + + /** + * Use this for user interface sounds, beeps, etcetera. + */ + ASSISTANCE_SONIFICATION = 13, + + /** + * Use this for game audio and sound effects. + */ + GAME = 14, + + /** + * Use this for audio responses to user queries, audio instructions or help utterances. + */ + ASSISTANT = 16, + + /** + * Use this in case of playing sounds in an emergency. + * Privileged MODIFY_AUDIO_ROUTING permission required. + */ + EMERGENCY = AAUDIO_SYSTEM_USAGE_OFFSET, + + /** + * Use this for safety sounds and alerts, for example backup camera obstacle detection. + * Privileged MODIFY_AUDIO_ROUTING permission required. + */ + SAFETY = AAUDIO_SYSTEM_USAGE_OFFSET + 1, + + /** + * Use this for vehicle status alerts and information, for example the check engine light. + * Privileged MODIFY_AUDIO_ROUTING permission required. + */ + VEHICLE_STATUS = AAUDIO_SYSTEM_USAGE_OFFSET + 2, + + /** + * Use this for traffic announcements, etc. + * Privileged MODIFY_AUDIO_ROUTING permission required. + */ + ANNOUNCEMENT = AAUDIO_SYSTEM_USAGE_OFFSET + 3, +} + +/** + * The CONTENT_TYPE attribute describes "what" you are playing. + * It expresses the general category of the content. This information is optional. + * But in case it is known (for instance AAUDIO_CONTENT_TYPE_MOVIE for a + * movie streaming service or AAUDIO_CONTENT_TYPE_SPEECH for + * an audio book application) this information might be used by the audio framework to + * enforce audio focus. + * + * Note that these match the equivalent values in + * AudioAttributes + * in the Android Java API. + * + * Added in API level 28. + */ +AAudioContentType :: enum i32 { + + /** + * Use this for spoken voice, audio books, etcetera. + */ + SPEECH = 1, + + /** + * Use this for pre-recorded or live music. + */ + MUSIC = 2, + + /** + * Use this for a movie or video soundtrack. + */ + MOVIE = 3, + + /** + * Use this for sound is designed to accompany a user action, + * such as a click or beep sound made when the user presses a button. + */ + SONIFICATION = 4 +} + +AAudioSpatializationBehavior :: enum i32 { + + /** + * Constant indicating the audio content associated with these attributes will follow the + * default platform behavior with regards to which content will be spatialized or not. + */ + AUTO = 1, + + /** + * Constant indicating the audio content associated with these attributes should never + * be spatialized. + */ + NEVER = 2, +} + +/** + * Defines the audio source. + * An audio source defines both a default physical source of audio signal, and a recording + * configuration. + * + * Note that these match the equivalent values in MediaRecorder.AudioSource in the Android Java API. + * + * Added in API level 28. + */ +AAudioInputPreset :: enum i32 { + /** + * Use this preset when other presets do not apply. + */ + GENERIC = 1, + + /** + * Use this preset when recording video. + */ + CAMCORDER = 5, + + /** + * Use this preset when doing speech recognition. + */ + VOICE_RECOGNITION = 6, + + /** + * Use this preset when doing telephony or voice messaging. + */ + VOICE_COMMUNICATION = 7, + + /** + * Use this preset to obtain an input with no effects. + * Note that this input will not have automatic gain control + * so the recorded volume may be very low. + */ + UNPROCESSED = 9, + + /** + * Use this preset for capturing audio meant to be processed in real time + * and played back for live performance (e.g karaoke). + * The capture path will minimize latency and coupling with playback path. + * Available since API level 29. + */ + VOICE_PERFORMANCE = 10, +} + +/** + * Specifying if audio may or may not be captured by other apps or the system. + * + * Note that these match the equivalent values in + * AudioAttributes + * in the Android Java API. + * + * Added in API level 29. + */ +AAudioAllowedCapturePolicy :: enum i32 { + /** + * Indicates that the audio may be captured by any app. + * + * For privacy, the following usages can not be recorded: AAUDIO_VOICE_COMMUNICATION*, + * AAUDIO_USAGE_NOTIFICATION*, AAUDIO_USAGE_ASSISTANCE* and {@link #AAUDIO_USAGE_ASSISTANT}. + * + * On Build.VERSION_CODES, + * this means only {@link #AAUDIO_USAGE_MEDIA} and {@link #AAUDIO_USAGE_GAME} may be captured. + * + * See + * ALLOW_CAPTURE_BY_ALL. + */ + ALLOW_CAPTURE_BY_ALL = 1, + /** + * Indicates that the audio may only be captured by system apps. + * + * System apps can capture for many purposes like accessibility, user guidance... + * but have strong restriction. See + * + * ALLOW_CAPTURE_BY_SYSTEM + * for what the system apps can do with the capture audio. + */ + ALLOW_CAPTURE_BY_SYSTEM = 2, + /** + * Indicates that the audio may not be recorded by any app, even if it is a system app. + * + * It is encouraged to use {@link #AAUDIO_ALLOW_CAPTURE_BY_SYSTEM} instead of this value as system apps + * provide significant and useful features for the user (eg. accessibility). + * See + * ALLOW_CAPTURE_BY_NONE. + */ + ALLOW_CAPTURE_BY_NONE = 3, +} + +/** + * These may be used with AAudioStreamBuilder_setSessionId(). + * + * Added in API level 28. + */ +AAudioSessionId :: enum i32 { + /** + * Do not allocate a session ID. + * Effects cannot be used with this stream. + * Default. + * + * Added in API level 28. + */ + NONE = -1, + + /** + * Allocate a session ID that can be used to attach and control + * effects using the Java AudioEffects API. + * Note that using this may result in higher latency. + * + * Note that this matches the value of AudioManager.AUDIO_SESSION_ID_GENERATE. + * + * Added in API level 28. + */ + ALLOCATE = 0, +} + +/** + * Defines the audio channel mask. + * Channel masks are used to describe the samples and their + * arrangement in the audio frame. They are also used in the endpoint + * (e.g. a USB audio interface, a DAC connected to headphones) to + * specify allowable configurations of a particular device. + * + * Added in API level 32. + */ +AAudioChannelMask :: enum u32 { + /** + * Invalid channel mask + */ + INVALID = 0xFFFFFFFF, // -1 + + /** + * Output audio channel mask + */ + FRONT_LEFT = 1 << 0, + FRONT_RIGHT = 1 << 1, + FRONT_CENTER = 1 << 2, + LOW_FREQUENCY = 1 << 3, + BACK_LEFT = 1 << 4, + BACK_RIGHT = 1 << 5, + FRONT_LEFT_OF_CENTER = 1 << 6, + FRONT_RIGHT_OF_CENTER = 1 << 7, + BACK_CENTER = 1 << 8, + SIDE_LEFT = 1 << 9, + SIDE_RIGHT = 1 << 10, + TOP_CENTER = 1 << 11, + TOP_FRONT_LEFT = 1 << 12, + TOP_FRONT_CENTER = 1 << 13, + TOP_FRONT_RIGHT = 1 << 14, + TOP_BACK_LEFT = 1 << 15, + TOP_BACK_CENTER = 1 << 16, + TOP_BACK_RIGHT = 1 << 17, + TOP_SIDE_LEFT = 1 << 18, + TOP_SIDE_RIGHT = 1 << 19, + BOTTOM_FRONT_LEFT = 1 << 20, + BOTTOM_FRONT_CENTER = 1 << 21, + BOTTOM_FRONT_RIGHT = 1 << 22, + LOW_FREQUENCY_2 = 1 << 23, + FRONT_WIDE_LEFT = 1 << 24, + FRONT_WIDE_RIGHT = 1 << 25, + + MONO = FRONT_LEFT, + STEREO = FRONT_LEFT | FRONT_RIGHT, + _2POINT1 = FRONT_LEFT | FRONT_RIGHT | LOW_FREQUENCY, + TRI = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER, + TRI_BACK = FRONT_LEFT | FRONT_RIGHT | BACK_CENTER, + _3POINT1 = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY, + _2POINT0POINT2 = FRONT_LEFT | FRONT_RIGHT | TOP_SIDE_LEFT | TOP_SIDE_RIGHT, + _2POINT1POINT2 = _2POINT0POINT2 | LOW_FREQUENCY, + _3POINT0POINT2 = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | TOP_SIDE_LEFT | TOP_SIDE_RIGHT, + _3POINT1POINT2 = _3POINT0POINT2 | LOW_FREQUENCY, + QUAD = FRONT_LEFT | FRONT_RIGHT | BACK_LEFT | BACK_RIGHT, + QUAD_SIDE = FRONT_LEFT | FRONT_RIGHT | SIDE_LEFT | SIDE_RIGHT, + SURROUND = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | BACK_CENTER, + PENTA = QUAD | FRONT_CENTER, + // aka 5POINT1_BACK + _5POINT1 = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | BACK_LEFT | BACK_RIGHT, + _5POINT1_SIDE = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | SIDE_LEFT | SIDE_RIGHT, + _6POINT1 = FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | BACK_LEFT | BACK_RIGHT | BACK_CENTER, + _7POINT1 = _5POINT1 | SIDE_LEFT | SIDE_RIGHT, + _5POINT1POINT2 = _5POINT1 | TOP_SIDE_LEFT | TOP_SIDE_RIGHT, + _5POINT1POINT4 = _5POINT1 | TOP_FRONT_LEFT | TOP_FRONT_RIGHT | TOP_BACK_LEFT | TOP_BACK_RIGHT, + _7POINT1POINT2 = _7POINT1 | TOP_SIDE_LEFT | TOP_SIDE_RIGHT, + _7POINT1POINT4 = _7POINT1 | TOP_FRONT_LEFT | TOP_FRONT_RIGHT | TOP_BACK_LEFT | TOP_BACK_RIGHT, + _9POINT1POINT4 = _7POINT1POINT4 | FRONT_WIDE_LEFT | FRONT_WIDE_RIGHT, + _9POINT1POINT6 = _9POINT1POINT4 | TOP_SIDE_LEFT | TOP_SIDE_RIGHT, + + FRONT_BACK = FRONT_CENTER | BACK_CENTER, +} + +/** +* Return one of these values from the data callback function. +*/ +AAudioDataCallbackResult :: enum i32 { + /** + * Continue calling the callback. + */ + CONTINUE = 0, + /** + * + Stop calling the callback. + * + * The application will still need to call AAudioStream_requestPause() + * or AAudioStream_requestStop(). + */ + STOP, +} + +AAudioStream :: struct{} +AAudioStreamBuilder :: struct{} + +/** +* Prototype for the data function that is passed to AAudioStreamBuilder_setDataCallback :: proc(). +* +* For an output stream, this function should render and write numFrames of data +* in the streams current data format to the audioData buffer. +* +* For an input stream, this function should read and process numFrames of data +* from the audioData buffer. +* +* The audio data is passed through the buffer. So do NOT call AAudioStream_read :: proc() or +* AAudioStream_write :: proc() on the stream that is making the callback. +* +* Note that numFrames can vary unless AAudioStreamBuilder_setFramesPerDataCallback :: proc() +* is called. +* +* Also note that this callback function should be considered a "real-time" function. +* It must not do anything that could cause an unbounded delay because that can cause the +* audio to glitch or pop. +* +* These are things the function should NOT do: +* +* +* The following are OK to call from the data callback: +* +* +* If you need to move data, eg. MIDI commands, in or out of the callback function then +* we recommend the use of non-blocking techniques such as an atomic FIFO. +* +* @param stream reference provided by AAudioStreamBuilder_openStream :: proc() +* @param userData the same address that was passed to AAudioStreamBuilder_setCallback :: proc() +* @param audioData a pointer to the audio data +* @param numFrames the number of frames to be processed, which can vary +* @return AAUDIO_CALLBACK_RESULT_* +*/ +AAudioStream_dataCallback :: #type proc "c" (stream: ^AAudioStream, userData: rawptr, audioData: rawptr, numFrames: i32) -> AAudioDataCallbackResult + +/** +* Prototype for the callback function that is passed to +* AAudioStreamBuilder_setErrorCallback :: proc(). +* +* The following may NOT be called from the error callback: +* +* +* The following are OK to call from the error callback: +* +* +* @param stream reference provided by AAudioStreamBuilder_openStream :: proc() +* @param userData the same address that was passed to AAudioStreamBuilder_setErrorCallback :: proc() +* @param error an AAUDIO_ERROR_* value. +*/ +AAudioStream_errorCallback :: #type proc "c" (stream: ^AAudioStream, userData: rawptr, error: AAudioResult) + +foreign aaudio { + /** + * The text is the ASCII symbol corresponding to the returnCode, + * or an English message saying the returnCode is unrecognized. + * This is intended for developers to use when debugging. + * It is not for display to users. + * + * Available since API level 26. + * + * @return pointer to a text representation of an AAudio result code. + */ + AAudio_convertResultToText :: proc(returnCode: AAudioResult) -> cstring --- + + /** + * The text is the ASCII symbol corresponding to the stream state, + * or an English message saying the state is unrecognized. + * This is intended for developers to use when debugging. + * It is not for display to users. + * + * Available since API level 26. + * + * @return pointer to a text representation of an AAudio state. + */ + AAudio_convertStreamStateToText :: proc(state: AAudioStreamState) -> cstring --- + + // ============================================================ + // StreamBuilder + // ============================================================ + + /** + * Create a StreamBuilder that can be used to open a Stream. + * + * The deviceId is initially unspecified, meaning that the current default device will be used. + * + * The default direction is {@link #AAUDIO_DIRECTION_OUTPUT}. + * The default sharing mode is {@link #AAUDIO_SHARING_MODE_SHARED}. + * The data format, samplesPerFrames and sampleRate are unspecified and will be + * chosen by the device when it is opened. + * + * AAudioStreamBuilder_delete :: proc() must be called when you are done using the builder. + * + * Available since API level 26. + */ + AAudio_createStreamBuilder :: proc(builder: ^^AAudioStreamBuilder) -> AAudioResult --- + + /** + * Request an audio device identified by an ID. + * + * The ID could be obtained from the Java AudioManager. + * AudioManager.getDevices :: proc() returns an array of {@link AudioDeviceInfo}, + * which contains a getId :: proc() method. That ID can be passed to this function. + * + * It is possible that you may not get the device that you requested. + * So if it is important to you, you should call + * AAudioStream_getDeviceId :: proc() after the stream is opened to + * verify the actual ID. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}, + * in which case the primary device will be used. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param deviceId device identifier or {@link #AAUDIO_UNSPECIFIED} + */ + AAudioStreamBuilder_setDeviceId :: proc(builder: ^AAudioStreamBuilder, deviceId: i32) --- + + /** + * Declare the name of the package creating the stream. + * + * This is usually {@code Context#getPackageName :: proc()}. + * + * The default, if you do not call this function, is a random package in the calling uid. + * The vast majority of apps have only one package per calling UID. + * If an invalid package name is set, input streams may not be given permission to + * record when started. + * + * The package name is usually the applicationId in your app's build.gradle file. + * + * Available since API level 31. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param packageName packageName of the calling app. + */ + AAudioStreamBuilder_setPackageName :: proc(builder: ^AAudioStreamBuilder, packageName: cstring) --- + + /** + * Declare the attribution tag of the context creating the stream. + * + * This is usually {@code Context#getAttributionTag :: proc()}. + * + * The default, if you do not call this function, is null. + * + * Available since API level 31. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param attributionTag attributionTag of the calling context. + */ + AAudioStreamBuilder_setAttributionTag :: proc(builder: ^AAudioStreamBuilder, attributionTag: cstring) --- + + /** + * Request a sample rate in Hertz. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}. + * An optimal value will then be chosen when the stream is opened. + * After opening a stream with an unspecified value, the application must + * query for the actual value, which may vary by device. + * + * If an exact value is specified then an opened stream will use that value. + * If a stream cannot be opened with the specified value then the open will fail. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param sampleRate frames per second. Common rates include 44100 and 48000 Hz. + */ + AAudioStreamBuilder_setSampleRate :: proc(builder: ^AAudioStreamBuilder, sampleRate: i32) --- + + /** + * Request a number of channels for the stream. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}. + * An optimal value will then be chosen when the stream is opened. + * After opening a stream with an unspecified value, the application must + * query for the actual value, which may vary by device. + * + * If an exact value is specified then an opened stream will use that value. + * If a stream cannot be opened with the specified value then the open will fail. + * + * As the channel count provided here may be different from the corresponding channel count + * of channel mask used in {@link AAudioStreamBuilder_setChannelMask}, the last called function + * will be respected if both this function and {@link AAudioStreamBuilder_setChannelMask} are + * called. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param channelCount Number of channels desired. + */ + AAudioStreamBuilder_setChannelCount :: proc(builder: ^AAudioStreamBuilder, channelCount: i32) --- + + /** + * Identical to AAudioStreamBuilder_setChannelCount :: proc(). + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param samplesPerFrame Number of samples in a frame. + * + * @deprecated use {@link AAudioStreamBuilder_setChannelCount} + */ + AAudioStreamBuilder_setSamplesPerFrame :: proc(builder: ^AAudioStreamBuilder, samplesPerFrame: i32) --- + + /** + * Request a sample data format, for example {@link #AAUDIO_FORMAT_PCM_I16}. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}. + * An optimal value will then be chosen when the stream is opened. + * After opening a stream with an unspecified value, the application must + * query for the actual value, which may vary by device. + * + * If an exact value is specified then an opened stream will use that value. + * If a stream cannot be opened with the specified value then the open will fail. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param format common formats are {@link #AAUDIO_FORMAT_PCM_FLOAT} and + * {@link #AAUDIO_FORMAT_PCM_I16}. + */ + AAudioStreamBuilder_setFormat :: proc(builder: ^AAudioStreamBuilder, format: AAudioFormat) --- + + /** + * Request a mode for sharing the device. + * + * The default, if you do not call this function, is {@link #AAUDIO_SHARING_MODE_SHARED}. + * + * The requested sharing mode may not be available. + * The application can query for the actual mode after the stream is opened. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param sharingMode {@link #AAUDIO_SHARING_MODE_SHARED} or {@link #AAUDIO_SHARING_MODE_EXCLUSIVE} + */ + AAudioStreamBuilder_setSharingMode :: proc(builder: ^AAudioStreamBuilder, sharingMode: AAudioSharingMode) --- + + /** + * Request the direction for a stream. + * + * The default, if you do not call this function, is {@link #AAUDIO_DIRECTION_OUTPUT}. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param direction {@link #AAUDIO_DIRECTION_OUTPUT} or {@link #AAUDIO_DIRECTION_INPUT} + */ + AAudioStreamBuilder_setDirection :: proc(builder: ^AAudioStreamBuilder, direction: AAudioDirection) --- + + /** + * Set the requested buffer capacity in frames. + * The final AAudioStream capacity may differ, but will probably be at least this big. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param numFrames the desired buffer capacity in frames or {@link #AAUDIO_UNSPECIFIED} + */ + AAudioStreamBuilder_setBufferCapacityInFrames :: proc(builder: ^AAudioStreamBuilder, numFrames: i32) --- + + /** + * Set the requested performance mode. + * + * Supported modes are {@link #AAUDIO_PERFORMANCE_MODE_NONE}, + * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING} * and {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY}. + * + * The default, if you do not call this function, is {@link #AAUDIO_PERFORMANCE_MODE_NONE}. + * + * You may not get the mode you requested. + * You can call AAudioStream_getPerformanceMode :: proc() + * to find out the final mode for the stream. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param mode the desired performance mode, eg. {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY} + */ + AAudioStreamBuilder_setPerformanceMode :: proc(builder: ^AAudioStreamBuilder, mode: AAudioPerformanceMode) --- + + /** + * Set the intended use case for the output stream. + * + * The AAudio system will use this information to optimize the + * behavior of the stream. + * This could, for example, affect how volume and focus is handled for the stream. + * + * The default, if you do not call this function, is {@link #AAUDIO_USAGE_MEDIA}. + * + * Available since API level 28. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param usage the desired usage, eg. {@link #AAUDIO_USAGE_GAME} + */ + AAudioStreamBuilder_setUsage :: proc(builder: ^AAudioStreamBuilder, usage: AAudioUsage) --- + + /** + * Set the type of audio data that the output stream will carry. + * + * The AAudio system will use this information to optimize the + * behavior of the stream. + * This could, for example, affect whether a stream is paused when a notification occurs. + * + * The default, if you do not call this function, is {@link #AAUDIO_CONTENT_TYPE_MUSIC}. + * + * Available since API level 28. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param contentType the type of audio data, eg. {@link #AAUDIO_CONTENT_TYPE_SPEECH} + */ + AAudioStreamBuilder_setContentType :: proc(builder: ^AAudioStreamBuilder, contentType: AAudioContentType) --- + + /** + * Sets the behavior affecting whether spatialization will be used. + * + * The AAudio system will use this information to select whether the stream will go + * through a spatializer effect or not when the effect is supported and enabled. + * + * Available since API level 32. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param spatializationBehavior the desired behavior with regards to spatialization, eg. + * {@link #AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO} + */ + AAudioStreamBuilder_setSpatializationBehavior :: proc(builder: ^AAudioStreamBuilder, spatializationBehavior: AAudioSpatializationBehavior) --- + + /** + * Specifies whether the audio data of this output stream has already been processed for + * spatialization. + * + * If the stream has been processed for spatialization, setting this to true will prevent + * issues such as double-processing on platforms that will spatialize audio data. + * + * Available since API level 32. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param isSpatialized true if the content is already processed for binaural or transaural spatial + * rendering, false otherwise. + */ + AAudioStreamBuilder_setIsContentSpatialized :: proc(builder: ^AAudioStreamBuilder, isSpatialized: bool) --- + + /** + * Set the input (capture) preset for the stream. + * + * The AAudio system will use this information to optimize the + * behavior of the stream. + * This could, for example, affect which microphones are used and how the + * recorded data is processed. + * + * The default, if you do not call this function, is {@link #AAUDIO_INPUT_PRESET_VOICE_RECOGNITION}. + * That is because VOICE_RECOGNITION is the preset with the lowest latency + * on many platforms. + * + * Available since API level 28. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param inputPreset the desired configuration for recording + */ + AAudioStreamBuilder_setInputPreset :: proc(builder: ^AAudioStreamBuilder, inputPreset: AAudioInputPreset) --- + + /** + * Specify whether this stream audio may or may not be captured by other apps or the system. + * + * The default is {@link #AAUDIO_ALLOW_CAPTURE_BY_ALL}. + * + * Note that an application can also set its global policy, in which case the most restrictive + * policy is always applied. See + * + * setAllowedCapturePolicy :: proc(int) + * + * Available since API level 29. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param capturePolicy the desired level of opt-out from being captured. + */ + AAudioStreamBuilder_setAllowedCapturePolicy :: proc(builder: ^AAudioStreamBuilder, capturePolicy: AAudioAllowedCapturePolicy) --- + + /** Set the requested session ID. + * + * The session ID can be used to associate a stream with effects processors. + * The effects are controlled using the Android AudioEffect Java API. + * + * The default, if you do not call this function, is {@link #AAUDIO_SESSION_ID_NONE}. + * + * If set to {@link #AAUDIO_SESSION_ID_ALLOCATE} then a session ID will be allocated + * when the stream is opened. + * + * The allocated session ID can be obtained by calling AAudioStream_getSessionId :: proc() + * and then used with this function when opening another stream. + * This allows effects to be shared between streams. + * + * Session IDs from AAudio can be used with the Android Java APIs and vice versa. + * So a session ID from an AAudio stream can be passed to Java + * and effects applied using the Java AudioEffect API. + * + * Note that allocating or setting a session ID may result in a stream with higher latency. + * + * Allocated session IDs will always be positive and nonzero. + * + * Available since API level 28. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param sessionId an allocated sessionID or {@link #AAUDIO_SESSION_ID_ALLOCATE} + */ + AAudioStreamBuilder_setSessionId :: proc(builder: ^AAudioStreamBuilder, sessionId: AAudioSessionId) --- + + + /** Indicates whether this input stream must be marked as privacy sensitive or not. + * + * When true, this input stream is privacy sensitive and any concurrent capture + * is not permitted. + * + * This is off (false) by default except when the input preset is {@link #AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION} + * or {@link #AAUDIO_INPUT_PRESET_CAMCORDER}. + * + * Always takes precedence over default from input preset when set explicitly. + * + * Only relevant if the stream direction is {@link #AAUDIO_DIRECTION_INPUT}. + * + * Added in API level 30. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param privacySensitive true if capture from this stream must be marked as privacy sensitive, + * false otherwise. + */ + AAudioStreamBuilder_setPrivacySensitive :: proc(builder: ^AAudioStreamBuilder, privacySensitive: bool) --- + + /** + * Request that AAudio call this functions when the stream is running. + * + * Note that when using this callback, the audio data will be passed in or out + * of the function as an argument. + * So you cannot call AAudioStream_write :: proc() or AAudioStream_read() + * on the same stream that has an active data callback. + * + * The callback function will start being called after AAudioStream_requestStart :: proc() + * is called. + * It will stop being called after AAudioStream_requestPause :: proc() or + * AAudioStream_requestStop :: proc() is called. + * + * This callback function will be called on a real-time thread owned by AAudio. + * The low latency streams may have callback threads with higher priority than normal streams. + * See {@link #AAudioStream_dataCallback} for more information. + * + * Note that the AAudio callbacks will never be called simultaneously from multiple threads. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param callback pointer to a function that will process audio data. + * @param userData pointer to an application data structure that will be passed + * to the callback functions. + */ + AAudioStreamBuilder_setDataCallback :: proc(builder: ^AAudioStreamBuilder, callback: AAudioStream_dataCallback, userData: rawptr) --- + + /** + * Set the requested data callback buffer size in frames. + * See {@link #AAudioStream_dataCallback}. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}. + * + * For the lowest possible latency, do not call this function. AAudio will then + * call the dataProc callback function with whatever size is optimal. + * That size may vary from one callback to another. + * + * Only use this function if the application requires a specific number of frames for processing. + * The application might, for example, be using an FFT that requires + * a specific power-of-two sized buffer. + * + * AAudio may need to add additional buffering in order to adapt between the internal + * buffer size and the requested buffer size. + * + * If you do call this function then the requested size should be less than + * half the buffer capacity, to allow double buffering. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param numFrames the desired buffer size in frames or {@link #AAUDIO_UNSPECIFIED} + */ + AAudioStreamBuilder_setFramesPerDataCallback :: proc(builder: ^AAudioStreamBuilder, numFrames: i32) --- + + /** + * Request that AAudio call this function if any error occurs or the stream is disconnected. + * + * It will be called, for example, if a headset or a USB device is unplugged causing the stream's + * device to be unavailable or "disconnected". + * Another possible cause of error would be a timeout or an unanticipated internal error. + * + * In response, this function should signal or create another thread to stop + * and close this stream. The other thread could then reopen a stream on another device. + * Do not stop or close the stream, or reopen the new stream, directly from this callback. + * + * This callback will not be called because of actions by the application, such as stopping + * or closing a stream. + * + * Note that the AAudio callbacks will never be called simultaneously from multiple threads. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param callback pointer to a function that will be called if an error occurs. + * @param userData pointer to an application data structure that will be passed + * to the callback functions. + */ + AAudioStreamBuilder_setErrorCallback :: proc(builder: ^AAudioStreamBuilder, callback: AAudioStream_errorCallback, userData: rawptr) --- + + /** + * Open a stream based on the options in the StreamBuilder. + * + * AAudioStream_close :: proc() must be called when finished with the stream to recover + * the memory and to free the associated resources. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param stream pointer to a variable to receive the new stream reference + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStreamBuilder_openStream :: proc(builder: ^AAudioStreamBuilder, stream: ^^AAudioStream) -> AAudioResult --- + + /** + * Delete the resources associated with the StreamBuilder. + * + * Available since API level 26. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStreamBuilder_delete :: proc(builder: ^AAudioStreamBuilder) -> AAudioResult --- + + /** + * Set audio channel mask for the stream. + * + * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}. + * If both channel mask and count are not set, then stereo will then be chosen when the + * stream is opened. + * After opening a stream with an unspecified value, the application must query for the + * actual value, which may vary by device. + * + * If an exact value is specified then an opened stream will use that value. + * If a stream cannot be opened with the specified value then the open will fail. + * + * As the corresponding channel count of provided channel mask here may be different + * from the channel count used in {@link AAudioStreamBuilder_setChannelCount} or + * {@link AAudioStreamBuilder_setSamplesPerFrame}, the last called function will be + * respected if this function and {@link AAudioStreamBuilder_setChannelCount} or + * {@link AAudioStreamBuilder_setSamplesPerFrame} are called. + * + * Available since API level 32. + * + * @param builder reference provided by AAudio_createStreamBuilder :: proc() + * @param channelMask Audio channel mask desired. + */ + AAudioStreamBuilder_setChannelMask :: proc(builder: ^AAudioStreamBuilder, channelMask: AAudioChannelMask) --- + + // ============================================================ + // Stream Control + // ============================================================ + + /** + * Free the audio resources associated with a stream created by + * AAudioStreamBuilder_openStream :: proc(). + * AAudioStream_close :: proc() should be called at some point after calling + * this function. + * + * After this call, the stream will be in {@link #AAUDIO_STREAM_STATE_CLOSING} + * + * This function is useful if you want to release the audio resources immediately, + * but still allow queries to the stream to occur from other threads. This often + * happens if you are monitoring stream progress from a UI thread. + * + * NOTE: This function is only fully implemented for MMAP streams, + * which are low latency streams supported by some devices. + * On other "Legacy" streams some audio resources will still be in use + * and some callbacks may still be in process after this call. + * + * Available since API level 30. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_release :: proc(stream: ^AAudioStream) -> AAudioResult --- + + /** + * Delete the internal data structures associated with the stream created + * by AAudioStreamBuilder_openStream :: proc(). + * + * If AAudioStream_release :: proc() has not been called then it will be called automatically. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_close :: proc(stream: ^AAudioStream) -> AAudioResult --- + + /** + * Asynchronously request to start playing the stream. For output streams, one should + * write to the stream to fill the buffer before starting. + * Otherwise it will underflow. + * After this call the state will be in {@link #AAUDIO_STREAM_STATE_STARTING} or + * {@link #AAUDIO_STREAM_STATE_STARTED}. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_requestStart :: proc(stream: ^AAudioStream) -> AAudioResult --- + + /** + * Asynchronous request for the stream to pause. + * Pausing a stream will freeze the data flow but not flush any buffers. + * Use AAudioStream_requestStart :: proc() to resume playback after a pause. + * After this call the state will be in {@link #AAUDIO_STREAM_STATE_PAUSING} or + * {@link #AAUDIO_STREAM_STATE_PAUSED}. + * + * This will return {@link #AAUDIO_ERROR_UNIMPLEMENTED} for input streams. + * For input streams use AAudioStream_requestStop :: proc(). + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_requestPause :: proc(stream: ^AAudioStream) -> AAudioResult --- + + /** + * Asynchronous request for the stream to flush. + * Flushing will discard any pending data. + * This call only works if the stream is pausing or paused. TODO review + * Frame counters are not reset by a flush. They may be advanced. + * After this call the state will be in {@link #AAUDIO_STREAM_STATE_FLUSHING} or + * {@link #AAUDIO_STREAM_STATE_FLUSHED}. + * + * This will return {@link #AAUDIO_ERROR_UNIMPLEMENTED} for input streams. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_requestFlush :: proc(stream: ^AAudioStream) -> AAudioResult --- + + /** + * Asynchronous request for the stream to stop. + * The stream will stop after all of the data currently buffered has been played. + * After this call the state will be in {@link #AAUDIO_STREAM_STATE_STOPPING} or + * {@link #AAUDIO_STREAM_STATE_STOPPED}. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_requestStop :: proc(stream: ^AAudioStream) -> AAudioResult --- + + /** + * Query the current state of the client, eg. {@link #AAUDIO_STREAM_STATE_PAUSING} + * + * This function will immediately return the state without updating the state. + * If you want to update the client state based on the server state then + * call AAudioStream_waitForStateChange :: proc() with currentState + * set to {@link #AAUDIO_STREAM_STATE_UNKNOWN} and a zero timeout. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + */ + AAudioStream_getState :: proc(stream: ^AAudioStream) -> AAudioStreamState --- + + /** + * Wait until the current state no longer matches the input state. + * + * This will update the current client state. + * + *

+	* AAudioResult result = AAUDIO_OK
+	* AAudioStreamState currentState = AAudioStream_getState :: proc(stream)
+	* AAudioStreamState inputState = currentState
+	* while (result == AAUDIO_OK && currentState != AAUDIO_STREAM_STATE_PAUSED) {
+	*     result = AAudioStream_waitForStateChange :: proc(
+	*                                   stream, inputState, ¤tState, MY_TIMEOUT_NANOS)
+	*     inputState = currentState
+	* }
+	* 
+ * + * Available since API level 26. + * + * @param stream A reference provided by AAudioStreamBuilder_openStream :: proc() + * @param inputState The state we want to avoid. + * @param nextState Pointer to a variable that will be set to the new state. + * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. + * @return {@link #AAUDIO_OK} or a negative error. + */ + AAudioStream_waitForStateChange :: proc(stream: ^AAudioStream, inputState: AAudioStreamState, nextState: ^AAudioStreamState, timeoutNanoseconds: i64) -> AAudioResult --- + + // ============================================================ + // Stream I/O + // ============================================================ + + /** + * Read data from the stream. + * + * The call will wait until the read is complete or until it runs out of time. + * If timeoutNanos is zero then this call will not wait. + * + * Note that timeoutNanoseconds is a relative duration in wall clock time. + * Time will not stop if the thread is asleep. + * So it will be implemented using CLOCK_BOOTTIME. + * + * This call is "strong non-blocking" unless it has to wait for data. + * + * If the call times out then zero or a partial frame count will be returned. + * + * Available since API level 26. + * + * @param stream A stream created using AAudioStreamBuilder_openStream :: proc(). + * @param buffer The address of the first sample. + * @param numFrames Number of frames to read. Only complete frames will be written. + * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. + * @return The number of frames actually read or a negative error. + */ + AAudioStream_read :: proc(stream: ^AAudioStream, buffer: rawptr, numFrames: i32, timeoutNanoseconds: i64) -> AAudioResult --- + + /** + * Write data to the stream. + * + * The call will wait until the write is complete or until it runs out of time. + * If timeoutNanos is zero then this call will not wait. + * + * Note that timeoutNanoseconds is a relative duration in wall clock time. + * Time will not stop if the thread is asleep. + * So it will be implemented using CLOCK_BOOTTIME. + * + * This call is "strong non-blocking" unless it has to wait for room in the buffer. + * + * If the call times out then zero or a partial frame count will be returned. + * + * Available since API level 26. + * + * @param stream A stream created using AAudioStreamBuilder_openStream :: proc(). + * @param buffer The address of the first sample. + * @param numFrames Number of frames to write. Only complete frames will be written. + * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. + * @return The number of frames actually written or a negative error. + */ + AAudioStream_write :: proc(stream: ^AAudioStream, buffer: rawptr, numFrames: i32, timeoutNanoseconds: i64) -> AAudioResult --- + + // ============================================================ + // Stream - queries + // ============================================================ + + /** + * This can be used to adjust the latency of the buffer by changing + * the threshold where blocking will occur. + * By combining this with AAudioStream_getXRunCount :: proc(), the latency can be tuned + * at run-time for each device. + * + * This cannot be set higher than AAudioStream_getBufferCapacityInFrames :: proc(). + * + * Note that you will probably not get the exact size you request. + * You can check the return value or call AAudioStream_getBufferSizeInFrames :: proc() + * to see what the actual final size is. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @param numFrames requested number of frames that can be filled without blocking + * @return actual buffer size in frames or a negative error + */ + AAudioStream_setBufferSizeInFrames :: proc(stream: ^AAudioStream, numFrames: i32) -> AAudioResult --- + + /** + * Query the maximum number of frames that can be filled without blocking. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return buffer size in frames. + */ + AAudioStream_getBufferSizeInFrames :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Query the number of frames that the application should read or write at + * one time for optimal performance. It is OK if an application writes + * a different number of frames. But the buffer size may need to be larger + * in order to avoid underruns or overruns. + * + * Note that this may or may not match the actual device burst size. + * For some endpoints, the burst size can vary dynamically. + * But these tend to be devices with high latency. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return burst size + */ + AAudioStream_getFramesPerBurst :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Query maximum buffer capacity in frames. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return buffer capacity in frames + */ + AAudioStream_getBufferCapacityInFrames :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Query the size of the buffer that will be passed to the dataProc callback + * in the numFrames parameter. + * + * This call can be used if the application needs to know the value of numFrames before + * the stream is started. This is not normally necessary. + * + * If a specific size was requested by calling + * AAudioStreamBuilder_setFramesPerDataCallback :: proc() then this will be the same size. + * + * If AAudioStreamBuilder_setFramesPerDataCallback :: proc() was not called then this will + * return the size chosen by AAudio, or {@link #AAUDIO_UNSPECIFIED}. + * + * {@link #AAUDIO_UNSPECIFIED} indicates that the callback buffer size for this stream + * may vary from one dataProc callback to the next. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return callback buffer size in frames or {@link #AAUDIO_UNSPECIFIED} + */ + AAudioStream_getFramesPerDataCallback :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * An XRun is an Underrun or an Overrun. + * During playing, an underrun will occur if the stream is not written in time + * and the system runs out of valid data. + * During recording, an overrun will occur if the stream is not read in time + * and there is no place to put the incoming data so it is discarded. + * + * An underrun or overrun can cause an audible "pop" or "glitch". + * + * Note that some INPUT devices may not support this function. + * In that case a 0 will always be returned. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return the underrun or overrun count + */ + AAudioStream_getXRunCount :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual sample rate + */ + AAudioStream_getSampleRate :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * A stream has one or more channels of data. + * A frame will contain one sample for each channel. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual number of channels + */ + AAudioStream_getChannelCount :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Identical to AAudioStream_getChannelCount :: proc(). + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual number of samples frame + */ + AAudioStream_getSamplesPerFrame :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual device ID + */ + AAudioStream_getDeviceId :: proc(stream: ^AAudioStream) -> i32 --- + + /** + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual data format + */ + AAudioStream_getFormat :: proc(stream: ^AAudioStream) -> AAudioFormat --- + + /** + * Provide actual sharing mode. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual sharing mode + */ + AAudioStream_getSharingMode :: proc(stream: ^AAudioStream) -> AAudioSharingMode --- + + /** + * Get the performance mode used by the stream. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + */ + AAudioStream_getPerformanceMode :: proc(stream: ^AAudioStream) -> AAudioPerformanceMode --- + + /** + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return direction + */ + AAudioStream_getDirection :: proc(stream: ^AAudioStream) -> AAudioDirection --- + + /** + * Passes back the number of frames that have been written since the stream was created. + * For an output stream, this will be advanced by the application calling write :: proc() + * or by a data callback. + * For an input stream, this will be advanced by the endpoint. + * + * The frame position is monotonically increasing. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return frames written + */ + AAudioStream_getFramesWritten :: proc(stream: ^AAudioStream) -> i64 --- + + /** + * Passes back the number of frames that have been read since the stream was created. + * For an output stream, this will be advanced by the endpoint. + * For an input stream, this will be advanced by the application calling read :: proc() + * or by a data callback. + * + * The frame position is monotonically increasing. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return frames read + */ + AAudioStream_getFramesRead :: proc(stream: ^AAudioStream) -> i64 --- + + /** + * Passes back the session ID associated with this stream. + * + * The session ID can be used to associate a stream with effects processors. + * The effects are controlled using the Android AudioEffect Java API. + * + * If AAudioStreamBuilder_setSessionId :: proc() was + * called with {@link #AAUDIO_SESSION_ID_ALLOCATE} + * then a new session ID should be allocated once when the stream is opened. + * + * If AAudioStreamBuilder_setSessionId :: proc() was called with a previously allocated + * session ID then that value should be returned. + * + * If AAudioStreamBuilder_setSessionId :: proc() was not called then this function should + * return {@link #AAUDIO_SESSION_ID_NONE}. + * + * The sessionID for a stream should not change once the stream has been opened. + * + * Available since API level 28. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return session ID or {@link #AAUDIO_SESSION_ID_NONE} + */ + AAudioStream_getSessionId :: proc(stream: ^AAudioStream) -> AAudioSessionId --- + + /** + * Passes back the time at which a particular frame was presented. + * This can be used to synchronize audio with video or MIDI. + * It can also be used to align a recorded stream with a playback stream. + * + * Timestamps are only valid when the stream is in {@link #AAUDIO_STREAM_STATE_STARTED}. + * {@link #AAUDIO_ERROR_INVALID_STATE} will be returned if the stream is not started. + * Note that because requestStart :: proc() is asynchronous, timestamps will not be valid until + * a short time after calling requestStart :: proc(). + * So {@link #AAUDIO_ERROR_INVALID_STATE} should not be considered a fatal error. + * Just try calling again later. + * + * If an error occurs, then the position and time will not be modified. + * + * The position and time passed back are monotonically increasing. + * + * Available since API level 26. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @param clockid CLOCK_MONOTONIC or CLOCK_BOOTTIME + * @param framePosition pointer to a variable to receive the position + * @param timeNanoseconds pointer to a variable to receive the time + * @return {@link #AAUDIO_OK} or a negative error + */ + AAudioStream_getTimestamp :: proc(stream: ^AAudioStream, clockid: clockid_t, framePosition: ^i64, timeNanoseconds: ^i64) -> AAudioResult --- + + /** + * Return the use case for the stream. + * + * Available since API level 28. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return frames read + */ + AAudioStream_getUsage :: proc(stream: ^AAudioStream) -> AAudioUsage --- + + /** + * Return the content type for the stream. + * + * Available since API level 28. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return content type, for example {@link #AAUDIO_CONTENT_TYPE_MUSIC} + */ + AAudioStream_getContentType :: proc(stream: ^AAudioStream) -> AAudioContentType --- + + /** + * Return the spatialization behavior for the stream. + * + * If none was explicitly set, it will return the default + * {@link #AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO} behavior. + * + * Available since API level 32. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return spatialization behavior, for example {@link #AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO} + */ + AAudioStream_getSpatializationBehavior :: proc(stream: ^AAudioStream) -> AAudioSpatializationBehavior --- + + /** + * Return whether the content of the stream is spatialized. + * + * Available since API level 32. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return true if the content is spatialized + */ + AAudioStream_isContentSpatialized :: proc(stream: ^AAudioStream) -> bool --- + + + /** + * Return the input preset for the stream. + * + * Available since API level 28. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return input preset, for example {@link #AAUDIO_INPUT_PRESET_CAMCORDER} + */ + AAudioStream_getInputPreset :: proc(stream: ^AAudioStream) -> AAudioInputPreset --- + + /** + * Return the policy that determines whether the audio may or may not be captured + * by other apps or the system. + * + * Available since API level 29. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return the allowed capture policy, for example {@link #AAUDIO_ALLOW_CAPTURE_BY_ALL} + */ + AAudioStream_getAllowedCapturePolicy :: proc(stream: ^AAudioStream) -> AAudioAllowedCapturePolicy --- + + + /** + * Return whether this input stream is marked as privacy sensitive or not. + * + * See {@link #AAudioStreamBuilder_setPrivacySensitive :: proc()}. + * + * Added in API level 30. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return true if privacy sensitive, false otherwise + */ + AAudioStream_isPrivacySensitive :: proc(stream: ^AAudioStream) -> bool --- + + /** + * Return the channel mask for the stream. This will be the mask set using + * {@link #AAudioStreamBuilder_setChannelMask}, or {@link #AAUDIO_UNSPECIFIED} otherwise. + * + * Available since API level 32. + * + * @param stream reference provided by AAudioStreamBuilder_openStream :: proc() + * @return actual channel mask + */ + AAudioStream_getChannelMask :: proc(stream: ^AAudioStream) -> AAudioChannelMask --- +} diff --git a/amidi/AMidi.odin b/amidi/AMidi.odin new file mode 100644 index 0000000..21cae7d --- /dev/null +++ b/amidi/AMidi.odin @@ -0,0 +1,329 @@ +//+build android +package amidi + +foreign import amidi "system:amidi" + +/* + * Message Op Codes. Used to parse MIDI data packets + */ +AMidiOpcode :: enum i32 { + DATA = 1, /* The MIDI packet contains normal MIDI data */ + FLUSH = 2, /* The MIDI packet contains just a MIDI FLUSH command. */ + /* Forces the send of any pending MIDI data. */ +} + +/* + * Type IDs for various MIDI devices. + */ +AMidiDeviceType :: enum i32 { + USB = 1, /* A MIDI device connected to the Android USB port */ + VIRTUAL = 2, /* A software object implementing MidiDeviceService */ + BLUETOOTH = 3 /* A MIDI device connected via BlueTooth */ +} + +/* + * Protocol IDs for various MIDI devices. + * + * Introduced in API 33. + */ +AMidiDevice_Protocol :: enum i32 { + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use UMP to negotiate with the device with MIDI-CI. + * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec. + */ + UMP_USE_MIDI_CI = 0, + + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use MIDI 1.0 through UMP with packet sizes up to 64 bits. + */ + UMP_MIDI_1_0_UP_TO_64_BITS = 1, + + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use MIDI 1.0 through UMP with packet sizes up to 64 bits and jitter reduction timestamps. + */ + UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2, + + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use MIDI 1.0 through UMP with packet sizes up to 128 bits. + */ + UMP_MIDI_1_0_UP_TO_128_BITS = 3, + + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use MIDI 1.0 through UMP with packet sizes up to 128 bits and jitter reduction timestamps. + */ + UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4, + + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use MIDI 2.0 through UMP. + */ + UMP_MIDI_2_0 = 17, + + /** + * Constant representing a default protocol with Universal MIDI Packets (UMP). + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * All UMP data should be a multiple of 4 bytes. + * Use MIDI 2.0 through UMP and jitter reduction timestamps. + */ + UMP_MIDI_2_0_AND_JRTS = 18, + + /** + * Constant representing a device with an unknown default protocol. + * If Universal MIDI Packets (UMP) are needed, use MIDI-CI through MIDI 1.0. + * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec. + * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec. + */ + UNKNOWN = -1 +} + +AMidiDevice :: struct{} +AMidiInputPort :: struct{} +AMidiOutputPort :: struct{} + +foreign amidi { + /* + * Device API + */ + /** + * Connects a native Midi Device object to the associated Java MidiDevice object. Use this + * AMidiDevice to access the rest of the native MIDI API. Use AMidiDevice_release() to + * disconnect from the Java object when not being used any more. + * + * @param env Points to the Java Environment. + * @param midiDeviceObj The Java MidiDevice Object. + * @param outDevicePtrPtr Points to the pointer to receive the AMidiDevice + * + * @return AMEDIA_OK on success, or a negative error value: + * @see AMEDIA_ERROR_INVALID_OBJECT - the midiDeviceObj + * is null or already connected to a native AMidiDevice + * @see AMEDIA_ERROR_UNKNOWN - an unknown error occurred. + * + * Available since API level 29. + */ + AMidiDevice_fromJava :: proc(env: ^JNIEnv, midiDeviceObj: jobject, outDevicePtrPtr: ^^AMidiDevice) -> media_status_t --- + + /** + * Disconnects the native Midi Device Object from the associated Java MidiDevice object. + * + * @param midiDevice Points to the native AMIDI_MidiDevice. + * + * @return AMEDIA_OK on success, + * or a negative error value: + * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. + * @see AMEDIA_ERROR_INVALID_OBJECT - the device is not consistent with the associated Java MidiDevice. + * @see AMEDIA_ERROR_INVALID_OBJECT - the JNI interface initialization to the associated java MidiDevice failed. + * @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info. + * + * Available since API level 29. + */ + AMidiDevice_release :: proc(midiDevice: ^AMidiDevice) -> media_status_t --- + + /** + * Gets the MIDI device type. + * + * @param device Specifies the MIDI device. + * + * @return The identifier of the MIDI device type: + * AMIDI_DEVICE_TYPE_USB + * AMIDI_DEVICE_TYPE_VIRTUAL + * AMIDI_DEVICE_TYPE_BLUETOOTH + * or a negative error value: + * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. + * @see AMEDIA_ERROR_UNKNOWN - Unknown error. + * + * Available since API level 29. + */ + AMidiDevice_getType :: proc(device: ^AMidiDevice) -> i32 --- + + /** + * Gets the number of input (sending) ports available on the specified MIDI device. + * + * @param device Specifies the MIDI device. + * + * @return If successful, returns the number of MIDI input (sending) ports available on the + * device. If an error occurs, returns a negative value indicating the error: + * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. + * @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info. + * + * Available since API level 29. + */ + AMidiDevice_getNumInputPorts :: proc(device: ^AMidiDevice) -> int --- + + /** + * Gets the number of output (receiving) ports available on the specified MIDI device. + * + * @param device Specifies the MIDI device. + * + * @return If successful, returns the number of MIDI output (receiving) ports available on the + * device. If an error occurs, returns a negative value indicating the error: + * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. + * @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info. + * + * Available since API level 29. + */ + AMidiDevice_getNumOutputPorts :: proc(device: ^AMidiDevice) -> int --- + + /** + * Gets the MIDI device default protocol. + * + * @param device Specifies the MIDI device. + * + * @return The identifier of the MIDI device default protocol: + * AMIDI_DEVICE_PROTOCOL_UMP_USE_MIDI_CI + * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS + * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS + * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS + * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS + * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0 + * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0_AND_JRTS + * AMIDI_DEVICE_PROTOCOL_UNKNOWN + * + * Most devices should return PROTOCOL_UNKNOWN (-1). This is intentional as devices + * with default UMP support are not backwards compatible. When the device is null, + * return AMIDI_DEVICE_PROTOCOL_UNKNOWN. + * + * Available since API 33. + */ + AMidiDevice_getDefaultProtocol :: proc(device: AMidiDevice) -> AMidiDevice_Protocol --- + + /* + * API for receiving data from the Output port of a device. + */ + /** + * Opens the output port so that the client can receive data from it. The port remains open and + * valid until AMidiOutputPort_close() is called for the returned AMidiOutputPort. + * + * @param device Specifies the MIDI device. + * @param portNumber Specifies the zero-based port index on the device to open. This value ranges + * between 0 and one less than the number of output ports reported by the + * AMidiDevice_getNumOutputPorts function. + * @param outOutputPortPtr Receives the native API port identifier of the opened port. + * + * @return AMEDIA_OK, or a negative error code: + * @see AMEDIA_ERROR_UNKNOWN - Unknown Error. + * + * Available since API level 29. + */ + AMidiOutputPort_open :: proc(device: ^AMidiDevice, portNumber: i32, outOutputPortPtr: ^^AMidiOutputPort) -> media_status_t --- + + /** + * Closes the output port. + * + * @param outputPort The native API port identifier of the port. + * + * Available since API level 29. + */ + AMidiOutputPort_close :: proc(outputPort: ^AMidiOutputPort) --- + + /** + * Receives the next pending MIDI message. To retrieve all pending messages, the client should + * repeatedly call this method until it returns 0. + * + * Note that this is a non-blocking call. If there are no Midi messages are available, the function + * returns 0 immediately (for 0 messages received). + * + * @param outputPort Identifies the port to receive messages from. + * @param opcodePtr Receives the message Op Code. + * @param buffer Points to the buffer to receive the message data bytes. + * @param maxBytes Specifies the size of the buffer pointed to by the buffer parameter. + * @param numBytesReceivedPtr On exit, receives the actual number of bytes stored in buffer. + * @param outTimestampPtr If non-NULL, receives the timestamp associated with the message. + * (the current value of the running Java Virtual Machine's high-resolution time source, + * in nanoseconds) + * @return the number of messages received (either 0 or 1), or a negative error code: + * @see AMEDIA_ERROR_UNKNOWN - Unknown Error. + * + * Available since API level 29. + */ + AMidiOutputPort_receive :: proc(outputPort: ^AMidiOutputPort, opcodePtr: ^AMidiOpcode, buffer: [^]byte, maxBytes: uint, numBytesReceivedPtr: ^uint, outTimestampPtr: ^i64) -> int --- + + /* + * API for sending data to the Input port of a device. + */ + /** + * Opens the input port so that the client can send data to it. The port remains open and + * valid until AMidiInputPort_close() is called for the returned AMidiInputPort. + * + * @param device Specifies the MIDI device. + * @param portNumber Specifies the zero-based port index on the device to open. This value ranges + * between 0 and one less than the number of input ports reported by the + * AMidiDevice_getNumInputPorts() function.. + * @param outInputPortPtr Receives the native API port identifier of the opened port. + * + * @return AMEDIA_OK, or a negative error code: + * @see AMEDIA_ERROR_UNKNOWN - Unknown Error. + * + * Available since API level 29. + */ + AMidiInputPort_open :: proc(device: ^AMidiDevice, portNumber: i32, outInputPortPtr: ^^AMidiInputPort) -> media_status_t --- + + /** + * Sends data to the specified input port. + * + * @param inputPort The identifier of the port to send data to. + * @param buffer Points to the array of bytes containing the data to send. + * @param numBytes Specifies the number of bytes to write. + * + * @return The number of bytes sent, which could be less than specified or a negative error code: + * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL. + * + * Available since API level 29. + */ + AMidiInputPort_send :: proc(inputPort: ^AMidiInputPort, buffer: [^]byte, numBytes: uint) -> int --- + + /** + * Sends data to the specified input port with a timestamp. + * + * @param inputPort The identifier of the port to send data to. + * @param buffer Points to the array of bytes containing the data to send. + * @param numBytes Specifies the number of bytes to write. + * @param timestamp The CLOCK_MONOTONIC time in nanoseconds to associate with the sent data. + * + * @return The number of bytes sent, which could be less than specified or a negative error code: + * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL. + * + * Available since API level 29. + */ + AMidiInputPort_sendWithTimestamp :: proc(inputPort: ^AMidiInputPort, buffer: [^]byte, numBytes: uint, timestamp: i64) -> int --- + + /** + * Sends a message with a 'MIDI flush command code' to the specified port. This should cause + * a receiver to discard any pending MIDI data it may have accumulated and not processed. + * + * @param inputPort The identifier of the port to send the flush command to. + * + * @returns @see AMEDIA_OK if successful, otherwise a negative error code: + * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL + * @see AMEDIA_ERROR_UNSUPPORTED - The FLUSH command couldn't + * be sent. + * + * Available since API level 29. + */ + AMidiInputPort_sendFlush :: proc(inputPort: ^AMidiInputPort) -> media_status_t --- + + /** + * Closes the input port. + * + * @param inputPort Identifies the input (sending) port to close. + * + * Available since API level 29. + */ + AMidiInputPort_close :: proc(inputPort: ^AMidiInputPort) --- +} diff --git a/android_native_app_glue.odin b/android_native_app_glue.odin index 7944dd5..fd40daa 100644 --- a/android_native_app_glue.odin +++ b/android_native_app_glue.odin @@ -122,7 +122,6 @@ android_poll_source :: struct { // Function to call to perform the standard processing of data from // this source. - //void (*process)(struct android_app* app, struct android_poll_source* source), process: #type proc "c" (app: ^android_app, source: ^android_poll_source), } diff --git a/media/NdkImage.odin b/media/NdkImage.odin new file mode 100644 index 0000000..e3316e4 --- /dev/null +++ b/media/NdkImage.odin @@ -0,0 +1,784 @@ +//+build android +package mediandk + +import "../" + +foreign import mediandk "system:mediandk" + +/** + * AImage supported formats: AImageReader only guarantees the support for the formats + * listed here. + */ +AImageFormats :: enum i32 { + /** + * 32 bits RGBA format, 8 bits for each of the four channels. + * + *

+ * Corresponding formats: + *

+ *

+ * + * @see AImage + * @see AImageReader + * @see AHardwareBuffer + */ + RGBA_8888 = 0x1, + + /** + * 32 bits RGBX format, 8 bits for each of the four channels. The values + * of the alpha channel bits are ignored (image is assumed to be opaque). + * + *

+ * Corresponding formats: + *

+ *

+ * + * @see AImage + * @see AImageReader + * @see AHardwareBuffer + */ + RGBX_8888 = 0x2, + + /** + * 24 bits RGB format, 8 bits for each of the three channels. + * + *

+ * Corresponding formats: + *

+ *

+ * + * @see AImage + * @see AImageReader + * @see AHardwareBuffer + */ + RGB_888 = 0x3, + + /** + * 16 bits RGB format, 5 bits for Red channel, 6 bits for Green channel, + * and 5 bits for Blue channel. + * + *

+ * Corresponding formats: + *

+ *

+ * + * @see AImage + * @see AImageReader + * @see AHardwareBuffer + */ + RGB_565 = 0x4, + + /** + * 64 bits RGBA format, 16 bits for each of the four channels. + * + *

+ * Corresponding formats: + *

+ *

+ * + * @see AImage + * @see AImageReader + * @see AHardwareBuffer + */ + RGBA_FP16 = 0x16, + + /** + * Multi-plane Android YUV 420 format. + * + *

This format is a generic YCbCr format, capable of describing any 4:2:0 + * chroma-subsampled planar or semiplanar buffer (but not fully interleaved), + * with 8 bits per color sample.

+ * + *

Images in this format are always represented by three separate buffers + * of data, one for each color plane. Additional information always + * accompanies the buffers, describing the row stride and the pixel stride + * for each plane.

+ * + *

The order of planes is guaranteed such that plane #0 is always Y, plane #1 is always + * U (Cb), and plane #2 is always V (Cr).

+ * + *

The Y-plane is guaranteed not to be interleaved with the U/V planes + * (in particular, pixel stride is always 1 in {@link AImage_getPlanePixelStride}).

+ * + *

The U/V planes are guaranteed to have the same row stride and pixel stride, that is, the + * return value of {@link AImage_getPlaneRowStride} for the U/V plane are guaranteed to be the + * same, and the return value of {@link AImage_getPlanePixelStride} for the U/V plane are also + * guaranteed to be the same.

+ * + *

For example, the {@link AImage} object can provide data + * in this format from a {@link ACameraDevice} through an {@link AImageReader} object.

+ * + *

This format is always supported as an output format for the android Camera2 NDK API.

+ * + * @see AImage + * @see AImageReader + * @see ACameraDevice + */ + YUV_420_888 = 0x23, + + /** + * Compressed JPEG format. + * + *

This format is always supported as an output format for the android Camera2 NDK API.

+ */ + JPEG = 0x100, + + /** + * 16 bits per pixel raw camera sensor image format, usually representing a single-channel + * Bayer-mosaic image. + * + *

The layout of the color mosaic, the maximum and minimum encoding + * values of the raw pixel data, the color space of the image, and all other + * needed information to interpret a raw sensor image must be queried from + * the {@link ACameraDevice} which produced the image.

+ */ + RAW16 = 0x20, + + /** + * Private raw camera sensor image format, a single channel image with implementation depedent + * pixel layout. + * + *

RAW_PRIVATE is a format for unprocessed raw image buffers coming from an + * image sensor. The actual structure of buffers of this format is implementation-dependent.

+ * + */ + RAW_PRIVATE = 0x24, + + /** + * Android 10-bit raw format. + * + *

+ * This is a single-plane, 10-bit per pixel, densely packed (in each row), + * unprocessed format, usually representing raw Bayer-pattern images coming + * from an image sensor. + *

+ *

+ * In an image buffer with this format, starting from the first pixel of + * each row, each 4 consecutive pixels are packed into 5 bytes (40 bits). + * Each one of the first 4 bytes contains the top 8 bits of each pixel, The + * fifth byte contains the 2 least significant bits of the 4 pixels, the + * exact layout data for each 4 consecutive pixels is illustrated below + * (Pi[j] stands for the jth bit of the ith pixel): + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
Byte 0:P0[9]P0[8]P0[7]P0[6]P0[5]P0[4]P0[3]P0[2]
Byte 1:P1[9]P1[8]P1[7]P1[6]P1[5]P1[4]P1[3]P1[2]
Byte 2:P2[9]P2[8]P2[7]P2[6]P2[5]P2[4]P2[3]P2[2]
Byte 3:P3[9]P3[8]P3[7]P3[6]P3[5]P3[4]P3[3]P3[2]
Byte 4:P3[1]P3[0]P2[1]P2[0]P1[1]P1[0]P0[1]P0[0]
+ *

+ * This format assumes + *

+ *

+ * + *
size = row stride * height
where the row stride is in bytes, + * not pixels. + * + *

+ * Since this is a densely packed format, the pixel stride is always 0. The + * application must use the pixel data layout defined in above table to + * access each row data. When row stride is equal to (width * (10 / 8)), there + * will be no padding bytes at the end of each row, the entire image data is + * densely packed. When stride is larger than (width * (10 / 8)), padding + * bytes will be present at the end of each row. + *

+ *

+ * For example, the {@link AImage} object can provide data in this format from a + * {@link ACameraDevice} (if supported) through a {@link AImageReader} object. + * The number of planes returned by {@link AImage_getNumberOfPlanes} will always be 1. + * The pixel stride is undefined ({@link AImage_getPlanePixelStride} will return + * {@link AMEDIA_ERROR_UNSUPPORTED}), and the {@link AImage_getPlaneRowStride} described the + * vertical neighboring pixel distance (in bytes) between adjacent rows. + *

+ * + * @see AImage + * @see AImageReader + * @see ACameraDevice + */ + RAW10 = 0x25, + + /** + * Android 12-bit raw format. + * + *

+ * This is a single-plane, 12-bit per pixel, densely packed (in each row), + * unprocessed format, usually representing raw Bayer-pattern images coming + * from an image sensor. + *

+ *

+ * In an image buffer with this format, starting from the first pixel of each + * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first + * and second byte contains the top 8 bits of first and second pixel. The third + * byte contains the 4 least significant bits of the two pixels, the exact layout + * data for each two consecutive pixels is illustrated below (Pi[j] stands for + * the jth bit of the ith pixel): + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
Byte 0:P0[11]P0[10]P0[ 9]P0[ 8]P0[ 7]P0[ 6]P0[ 5]P0[ 4]
Byte 1:P1[11]P1[10]P1[ 9]P1[ 8]P1[ 7]P1[ 6]P1[ 5]P1[ 4]
Byte 2:P1[ 3]P1[ 2]P1[ 1]P1[ 0]P0[ 3]P0[ 2]P0[ 1]P0[ 0]
+ *

+ * This format assumes + *

+ *

+ * + *
size = row stride * height
where the row stride is in bytes, + * not pixels. + * + *

+ * Since this is a densely packed format, the pixel stride is always 0. The + * application must use the pixel data layout defined in above table to + * access each row data. When row stride is equal to (width * (12 / 8)), there + * will be no padding bytes at the end of each row, the entire image data is + * densely packed. When stride is larger than (width * (12 / 8)), padding + * bytes will be present at the end of each row. + *

+ *

+ * For example, the {@link AImage} object can provide data in this format from a + * {@link ACameraDevice} (if supported) through a {@link AImageReader} object. + * The number of planes returned by {@link AImage_getNumberOfPlanes} will always be 1. + * The pixel stride is undefined ({@link AImage_getPlanePixelStride} will return + * {@link AMEDIA_ERROR_UNSUPPORTED}), and the {@link AImage_getPlaneRowStride} described the + * vertical neighboring pixel distance (in bytes) between adjacent rows. + *

+ * + * @see AImage + * @see AImageReader + * @see ACameraDevice + */ + RAW12 = 0x26, + + /** + * Android dense depth image format. + * + *

Each pixel is 16 bits, representing a depth ranging measurement from a depth camera or + * similar sensor. The 16-bit sample consists of a confidence value and the actual ranging + * measurement.

+ * + *

The confidence value is an estimate of correctness for this sample. It is encoded in the + * 3 most significant bits of the sample, with a value of 0 representing 100% confidence, a + * value of 1 representing 0% confidence, a value of 2 representing 1/7, a value of 3 + * representing 2/7, and so on.

+ * + *

As an example, the following sample extracts the range and confidence from the first pixel + * of a DEPTH16-format {@link AImage}, and converts the confidence to a floating-point value + * between 0 and 1.f inclusive, with 1.f representing maximum confidence: + * + *

+     *    uint16_t* data;
+     *    int dataLength;
+     *    AImage_getPlaneData(image, 0, (uint8_t**)&data, &dataLength);
+     *    uint16_t depthSample = data[0];
+     *    uint16_t depthRange = (depthSample & 0x1FFF);
+     *    uint16_t depthConfidence = ((depthSample >> 13) & 0x7);
+     *    float depthPercentage = depthConfidence == 0 ? 1.f : (depthConfidence - 1) / 7.f;
+     * 
+ *

+ * + *

This format assumes + *

+ *

+ * + *
 y_size = stride * height 
+ * + * When produced by a camera, the units for the range are millimeters. + */ + DEPTH16 = 0x44363159, + + /** + * Android sparse depth point cloud format. + * + *

A variable-length list of 3D points plus a confidence value, with each point represented + * by four floats; first the X, Y, Z position coordinates, and then the confidence value.

+ * + *

The number of points is ((size of the buffer in bytes) / 16). + * + *

The coordinate system and units of the position values depend on the source of the point + * cloud data. The confidence value is between 0.f and 1.f, inclusive, with 0 representing 0% + * confidence and 1.f representing 100% confidence in the measured position values.

+ * + *

As an example, the following code extracts the first depth point in a DEPTH_POINT_CLOUD + * format {@link AImage}: + *

+     *    float* data;
+     *    int dataLength;
+     *    AImage_getPlaneData(image, 0, (uint8_t**)&data, &dataLength);
+     *    float x = data[0];
+     *    float y = data[1];
+     *    float z = data[2];
+     *    float confidence = data[3];
+     * 
+ * + */ + DEPTH_POINT_CLOUD = 0x101, + + /** + * Android private opaque image format. + * + *

The choices of the actual format and pixel data layout are entirely up to the + * device-specific and framework internal implementations, and may vary depending on use cases + * even for the same device. Also note that the contents of these buffers are not directly + * accessible to the application.

+ * + *

When an {@link AImage} of this format is obtained from an {@link AImageReader} or + * {@link AImage_getNumberOfPlanes()} method will return zero.

+ */ + PRIVATE = 0x22, + + /** + * Android Y8 format. + * + *

Y8 is a planar format comprised of a WxH Y plane only, with each pixel + * being represented by 8 bits.

+ * + *

This format assumes + *

+ *

+ * + *
 size = stride * height 
+ * + *

For example, the {@link AImage} object can provide data + * in this format from a {@link ACameraDevice} (if supported) through a + * {@link AImageReader} object. The number of planes returned by + * {@link AImage_getNumberOfPlanes} will always be 1. The pixel stride returned by + * {@link AImage_getPlanePixelStride} will always be 1, and the + * {@link AImage_getPlaneRowStride} described the vertical neighboring pixel distance + * (in bytes) between adjacent rows.

+ * + */ + Y8 = 0x20203859, + + /** + * Compressed HEIC format. + * + *

This format defines the HEIC brand of High Efficiency Image File + * Format as described in ISO/IEC 23008-12.

+ */ + HEIC = 0x48454946, + + /** + * Depth augmented compressed JPEG format. + * + *

JPEG compressed main image along with XMP embedded depth metadata + * following ISO 16684-1:2011(E).

+ */ + DEPTH_JPEG = 0x69656963, +} + +/** + * AImage is an opaque type that provides access to image generated by {@link AImageReader}. + */ +AImage :: struct{} + +/** + * Data type describing an cropped rectangle returned by {@link AImage_getCropRect}. + * + *

Note that the right and bottom coordinates are exclusive, so the width of the rectangle is + * (right - left) and the height of the rectangle is (bottom - top).

+ */ +AImageCropRect :: struct { + left: i32, + top: i32, + right: i32, + bottom: i32, +} + +foreign mediandk { + /** + * Return the image back the the system and delete the AImage object from memory. + * + *

Do NOT use the image pointer after this method returns. + * Note that if the parent {@link AImageReader} is closed, all the {@link AImage} objects acquired + * from the parent reader will be returned to system. All AImage_* methods except this method will + * return {@link AMEDIA_ERROR_INVALID_OBJECT}. Application still needs to call this method on those + * {@link AImage} objects to fully delete the {@link AImage} object from memory.

+ * + * Available since API level 24. + * + * @param image The {@link AImage} to be deleted. + */ + AImage_delete :: proc(image: ^AImage) --- + + /** + * Query the width of the input {@link AImage}. + * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param width the width of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getWidth :: proc(image: ^AImage, width: ^i32) -> media_status_t --- + + /** + * Query the height of the input {@link AImage}. + * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param height the height of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getHeight :: proc(image: ^AImage, height: ^i32) -> media_status_t --- + + /** + * Query the format of the input {@link AImage}. + * + *

The format value will be one of AIMAGE_FORMAT_* enum value.

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param format the format of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getFormat :: proc(image: ^AImage, format: ^AImageFormats) -> media_status_t --- + + /** + * Query the cropped rectangle of the input {@link AImage}. + * + *

The crop rectangle specifies the region of valid pixels in the image, using coordinates in the + * largest-resolution plane.

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param rect the cropped rectangle of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getCropRect :: proc(image: ^AImage, rect: ^AImageCropRect) -> media_status_t --- + + /** + * Query the timestamp of the input {@link AImage}. + * + *

+ * The timestamp is measured in nanoseconds, and is normally monotonically increasing. The + * timestamps for the images from different sources may have different timebases therefore may not + * be comparable. The specific meaning and timebase of the timestamp depend on the source providing + * images. For images generated by camera, the timestamp value will match + * {@link ACAMERA_SENSOR_TIMESTAMP} of the {@link ACameraMetadata} in + * {@link ACameraCaptureSession_captureCallbacks#onCaptureStarted} and + * {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted} callback. + *

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param timestampNs the timestamp of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getTimestamp :: proc(image: ^AImage, timestampNs: ^i64) -> media_status_t --- + + /** + * Query the number of planes of the input {@link AImage}. + * + *

The number of plane of an {@link AImage} is determined by its format, which can be queried by + * {@link AImage_getFormat} method.

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param numPlanes the number of planes of the image will be filled here if the method call + * succeeeds. + * + * @return + */ + AImage_getNumberOfPlanes :: proc(image: ^AImage, numPlanes: ^i32) -> media_status_t --- + + /** + * Query the pixel stride of the input {@link AImage}. + * + *

This is the distance between two consecutive pixel values in a row of pixels. It may be + * larger than the size of a single pixel to account for interleaved image data or padded formats. + * Note that pixel stride is undefined for some formats such as {@link AIMAGE_FORMAT_RAW_PRIVATE}, + * and calling this method on images of these formats will cause {@link AMEDIA_ERROR_UNSUPPORTED} + * being returned. + * For formats where pixel stride is well defined, the pixel stride is always greater than 0.

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param planeIdx the index of the plane. Must be less than the number of planes of input image. + * @param pixelStride the pixel stride of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getPlanePixelStride :: proc(image: ^AImage, planeIdx: i32, pixelStride: ^i32) -> media_status_t --- + + /** + * Query the row stride of the input {@link AImage}. + * + *

This is the distance between the start of two consecutive rows of pixels in the image. Note + * that row stried is undefined for some formats such as {@link AIMAGE_FORMAT_RAW_PRIVATE}, and + * calling this method on images of these formats will cause {@link AMEDIA_ERROR_UNSUPPORTED} + * being returned. + * For formats where row stride is well defined, the row stride is always greater than 0.

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param planeIdx the index of the plane. Must be less than the number of planes of input image. + * @param rowStride the row stride of the image will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getPlaneRowStride :: proc(image: ^AImage, planeIdx: i32, rowStride: ^i32) -> media_status_t --- + + /** + * Get the data pointer of the input image for direct application access. + * + *

Note that once the {@link AImage} or the parent {@link AImageReader} is deleted, the data + * pointer from previous AImage_getPlaneData call becomes invalid. Do NOT use it after the + * {@link AImage} or the parent {@link AImageReader} is deleted.

+ * + * Available since API level 24. + * + * @param image the {@link AImage} of interest. + * @param planeIdx the index of the plane. Must be less than the number of planes of input image. + * @param data the data pointer of the image will be filled here if the method call succeeeds. + * @param dataLength the valid length of data will be filled here if the method call succeeeds. + * + * @return + */ + AImage_getPlaneData :: proc(image: ^AImage, planeIdx: i32, data: ^[^]u8, dataLength: ^i32) -> media_status_t --- + + /** + * Return the image back the the system and delete the AImage object from memory asynchronously. + * + *

Similar to {@link AImage_delete}, do NOT use the image pointer after this method returns. + * However, the caller can still hold on to the {@link AHardwareBuffer} returned from this image and + * signal the release of the hardware buffer back to the {@link AImageReader}'s queue using + * releaseFenceFd.

+ * + * Available since API level 26. + * + * @param image The {@link AImage} to be deleted. + * @param releaseFenceFd A sync fence fd defined in {@link sync.h}, which signals the release of + * underlying {@link AHardwareBuffer}. + * + * @see sync.h + */ + AImage_deleteAsync :: proc(image: ^AImage, releaseFenceFd: i32) --- + + /** + * Get the hardware buffer handle of the input image intended for GPU and/or hardware access. + * + *

Note that no reference on the returned {@link AHardwareBuffer} handle is acquired + * automatically. Once the {@link AImage} or the parent {@link AImageReader} is deleted, the + * {@link AHardwareBuffer} handle from previous {@link AImage_getHardwareBuffer} becomes + * invalid.

+ * + *

If the caller ever needs to hold on a reference to the {@link AHardwareBuffer} handle after + * the {@link AImage} or the parent {@link AImageReader} is deleted, it must call {@link + * AHardwareBuffer_acquire} to acquire an extra reference, and call {@link AHardwareBuffer_release} + * once it has finished using it in order to properly deallocate the underlying memory managed by + * {@link AHardwareBuffer}. If the caller has acquired extra reference on an {@link AHardwareBuffer} + * returned from this function, it must also register a listener using the function + * {@link AImageReader_setBufferRemovedListener} to be notified when the buffer is no longer used + * by {@link AImageReader}.

+ * + * Available since API level 26. + * + * @param image the {@link AImage} of interest. + * @param buffer The memory area pointed to by buffer will contain the acquired AHardwareBuffer + * handle. + * @return + * + * @see AImageReader_ImageCallback + */ + AImage_getHardwareBuffer :: proc(image: ^AImage, buffer: ^^android.AHardwareBuffer) -> media_status_t --- +} diff --git a/media/NdkImageReader.odin b/media/NdkImageReader.odin new file mode 100644 index 0000000..b499f53 --- /dev/null +++ b/media/NdkImageReader.odin @@ -0,0 +1,443 @@ +//+build android +package mediandk + +import "../" + +foreign import mediandk "system:mediandk" + +/** + * AImage is an opaque type that allows direct application access to image data rendered into a + * {@link ANativeWindow}. + */ +AImageReader :: struct{} + +AImageReader_ImageListener :: struct { + /// Optional application context passed as the first parameter of the callback. + _context: rawptr, + + /** + * This callback is called when there is a new image available in the image reader's queue. + * + *

The callback happens on one dedicated thread per {@link AImageReader} instance. It is okay + * to use AImageReader_* and AImage_* methods within the callback. Note that it is possible that + * calling {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage} + * returns {@link AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE} within this callback. For example, when + * there are multiple images and callbacks queued, if application called + * {@link AImageReader_acquireLatestImage}, some images will be returned to system before their + * corresponding callback is executed.

+ */ + onImageAvailable: AImageReader_ImageCallback, +} + +/** +* A listener to the AHardwareBuffer removal event, use +* {@link AImageReader_setBufferRemovedListener} to register the listener object to AImageReader. +*/ +AImageReader_BufferRemovedListener :: struct { + /// Optional application context passed as the first parameter of the callback. + _context: rawptr, + + /** + * This callback is called when an old {@link AHardwareBuffer} is about to be removed from the + * image reader. + * + *

Note that registering this callback is optional unless the user holds on extra reference + * to {@link AHardwareBuffer} returned from {@link AImage_getHardwareBuffer} by calling {@link + * AHardwareBuffer_acquire} or creating external graphic objects, such as EglImage, from it.

+ * + *

If the callback is registered, the {@link AImageReader} will hold on the last of its + * references to the {@link AHardwareBuffer} until this callback returns. User can use the + * callback to get notified that it becomes the last owner of the buffer. It is up to the user + * to decide to either 1) immediately release all of its references to the buffer or 2) keep + * using the buffer and release it in future. Note that, if option 2 if used, user of this API + * is responsible to deallocate the buffer properly by calling {@link AHardwareBuffer_release}. + *

+ * + * @see AHardwareBuffer_release + * @see AImage_getHardwareBuffer + */ + onBufferRemoved: AImageReader_BufferRemovedCallback, +} + +/** +* Signature of the callback which is called when a new image is available from {@link AImageReader}. +* +* @param context The optional application context provided by user in +* {@link AImageReader_setImageListener}. +* @param session The camera capture session whose state is changing. +*/ +AImageReader_ImageCallback :: #type proc "c" (_context: rawptr, reader: ^AImageReader) + +/** +* Signature of the callback which is called when {@link AImageReader} is about to remove a buffer. +* +* @param context The optional application context provided by user in +* {@link AImageReader_setBufferRemovedListener}. +* @param reader The {@link AImageReader} of interest. +* @param buffer The {@link AHardwareBuffer} that is being removed from this image reader. +*/ +AImageReader_BufferRemovedCallback :: #type proc "c" (_context: rawptr, reader: ^AImageReader, buffer: ^android.AHardwareBuffer) + +foreign mediandk { + /** + * Create a new reader for images of the desired size and format. + * + *

+ * The maxImages parameter determines the maximum number of {@link AImage} objects that can be + * acquired from the {@link AImageReader} simultaneously. Requesting more buffers will use up + * more memory, so it is important to use only the minimum number necessary for the use case. + *

+ *

+ * The valid sizes and formats depend on the source of the image data. + *

+ * + * Available since API level 24. + * + * @param width The default width in pixels of the Images that this reader will produce. + * @param height The default height in pixels of the Images that this reader will produce. + * @param format The format of the Image that this reader will produce. This must be one of the + * AIMAGE_FORMAT_* enum value defined in {@link AIMAGE_FORMATS}. Note that not all + * formats are supported. One example is {@link AIMAGE_FORMAT_PRIVATE}, as it is not + * intended to be read by applications directly. That format is supported by + * {@link AImageReader_newWithUsage} introduced in API 26. + * @param maxImages The maximum number of images the user will want to access simultaneously. This + * should be as small as possible to limit memory use. Once maxImages Images are obtained + * by the user, one of them has to be released before a new {@link AImage} will become + * available for access through {@link AImageReader_acquireLatestImage} or + * {@link AImageReader_acquireNextImage}. Must be greater than 0. + * @param reader The created image reader will be filled here if the method call succeeeds. + * + * @return + * + * @see AImage + */ + AImageReader_new :: proc(width: i32, height: i32, format: AImageFormats, maxImages: i32, reader: ^^AImageReader) -> media_status_t --- + + /** + * Delete an {@link AImageReader} and return all images generated by this reader to system. + * + *

This method will return all {@link AImage} objects acquired by this reader (via + * {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}) to system, + * making any of data pointers obtained from {@link AImage_getPlaneData} invalid. Do NOT access + * the reader object or any of those data pointers after this method returns.

+ * + * Available since API level 24. + * + * @param reader The image reader to be deleted. + */ + AImageReader_delete :: proc(reader: ^AImageReader) --- + + /** + * Get a {@link ANativeWindow} that can be used to produce {@link AImage} for this image reader. + * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param window The output {@link ANativeWindow} will be filled here if the method call succeeds. + * The {@link ANativeWindow} is managed by this image reader. Do NOT call + * {@link ANativeWindow_release} on it. Instead, use {@link AImageReader_delete}. + * + * @return + */ + AImageReader_getWindow :: proc(reader: ^AImageReader, window: ^^android.ANativeWindow) -> media_status_t --- + + /** + * Query the default width of the {@link AImage} generated by this reader, in pixels. + * + *

The width may be overridden by the producer sending buffers to this reader's + * {@link ANativeWindow}. If so, the actual width of the images can be found using + * {@link AImage_getWidth}.

+ * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param width the default width of the reader will be filled here if the method call succeeeds. + * + * @return + */ + AImageReader_getWidth :: proc(reader: ^AImageReader, width: ^i32) -> media_status_t --- + + /** + * Query the default height of the {@link AImage} generated by this reader, in pixels. + * + *

The height may be overridden by the producer sending buffers to this reader's + * {@link ANativeWindow}. If so, the actual height of the images can be found using + * {@link AImage_getHeight}.

+ * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param height the default height of the reader will be filled here if the method call succeeeds. + * + * @return + */ + AImageReader_getHeight :: proc(reader: ^AImageReader, height: ^i32) -> media_status_t --- + + /** + * Query the format of the {@link AImage} generated by this reader. + * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param format the fromat of the reader will be filled here if the method call succeeeds. The + * value will be one of the AIMAGE_FORMAT_* enum value defiend in {@link NdkImage.h}. + * + * @return + */ + AImageReader_getFormat :: proc(reader: ^AImageReader, format: ^AImageFormats) -> media_status_t --- + + /** + * Query the maximum number of concurrently acquired {@link AImage}s of this reader. + * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param maxImages the maximum number of concurrently acquired images of the reader will be filled + * here if the method call succeeeds. + * + * @return + */ + AImageReader_getMaxImages :: proc(reader: ^AImageReader, maxImages: ^i32) -> media_status_t --- + + /** + * Acquire the next {@link AImage} from the image reader's queue. + * + *

Warning: Consider using {@link AImageReader_acquireLatestImage} instead, as it will + * automatically release older images, and allow slower-running processing routines to catch + * up to the newest frame. Usage of {@link AImageReader_acquireNextImage} is recommended for + * batch/background processing. Incorrectly using this method can cause images to appear + * with an ever-increasing delay, followed by a complete stall where no new images seem to appear. + *

+ * + *

+ * This method will fail if {@link AImageReader_getMaxImages maxImages} have been acquired with + * {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}. In particular + * a sequence of {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage} + * calls greater than {@link AImageReader_getMaxImages maxImages} without calling + * {@link AImage_delete} in-between will exhaust the underlying queue. At such a time, + * {@link AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED} will be returned until more images are released with + * {@link AImage_delete}. + *

+ * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param image the acquired {@link AImage} will be filled here if the method call succeeeds. + * + * @return + * + * @see AImageReader_acquireLatestImage + */ + AImageReader_acquireNextImage :: proc(reader: ^AImageReader, image: ^^AImage) -> media_status_t --- + + /** + * Acquire the latest {@link AImage} from the image reader's queue, dropping older images. + * + *

+ * This operation will acquire all the images possible from the image reader, but + * {@link AImage_delete} all images that aren't the latest. This function is recommended to use over + * {@link AImageReader_acquireNextImage} for most use-cases, as it's more suited for real-time + * processing. + *

+ *

+ * Note that {@link AImageReader_getMaxImages maxImages} should be at least 2 for + * {@link AImageReader_acquireLatestImage} to be any different than + * {@link AImageReader_acquireNextImage} - discarding all-but-the-newest {@link AImage} requires + * temporarily acquiring two {@link AImage}s at once. Or more generally, calling + * {@link AImageReader_acquireLatestImage} with less than two images of margin, that is + * (maxImages - currentAcquiredImages < 2) will not discard as expected. + *

+ *

+ * This method will fail if {@link AImageReader_getMaxImages maxImages} have been acquired with + * {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}. In particular + * a sequence of {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage} + * calls greater than {@link AImageReader_getMaxImages maxImages} without calling + * {@link AImage_delete} in-between will exhaust the underlying queue. At such a time, + * {@link AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED} will be returned until more images are released with + * {@link AImage_delete}. + *

+ * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param image the acquired {@link AImage} will be filled here if the method call succeeeds. + * + * @return + * + * @see AImageReader_acquireNextImage + */ + AImageReader_acquireLatestImage :: proc(reader: ^AImageReader, image: ^^AImage) -> media_status_t --- + + + /** + * Set the onImageAvailable listener of this image reader. + * + * Calling this method will replace previously registered listeners. + * + * Available since API level 24. + * + * @param reader The image reader of interest. + * @param listener The {@link AImageReader_ImageListener} to be registered. Set this to NULL if + * the application no longer needs to listen to new images. + * + * @return + */ + AImageReader_setImageListener :: proc(reader: ^AImageReader, listener: ^AImageReader_ImageListener) -> media_status_t --- + + /** + * AImageReader constructor similar to {@link AImageReader_new} that takes an additional parameter + * for the consumer usage. All other parameters and the return values are identical to those passed + * to {@link AImageReader_new}. + * + *

If the \c format is {@link AIMAGE_FORMAT_PRIVATE}, the created {@link AImageReader} + * will produce images whose contents are not directly accessible by the application. The application can + * still acquire images from this {@link AImageReader} and access {@link AHardwareBuffer} via + * {@link AImage_getHardwareBuffer()}. The {@link AHardwareBuffer} gained this way can then + * be passed back to hardware (such as GPU or hardware encoder if supported) for future processing. + * For example, you can obtain an EGLClientBuffer from the {@link AHardwareBuffer} by using + * eglGetNativeClientBufferANDROID extension and pass that EGLClientBuffer to + * eglCreateImageKHR to create an EGLImage resource type, which may then be bound to a + * texture via glEGLImageTargetTexture2DOES on supported devices. This can be useful for + * transporting textures that may be shared cross-process.

+ *

In general, when software access to image data is not necessary, an {@link AImageReader} + * created with {@link AIMAGE_FORMAT_PRIVATE} format is more efficient, compared with {@link + * AImageReader}s using other format such as {@link AIMAGE_FORMAT_YUV_420_888}.

+ * + *

Note that not all format and usage flag combination is supported by the {@link AImageReader}, + * especially if \c format is {@link AIMAGE_FORMAT_PRIVATE}, \c usage must not include either + * {@link AHARDWAREBUFFER_USAGE_CPU_READ_RARELY} or {@link AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}

+ * + * @param width The default width in pixels of the Images that this reader will produce. + * @param height The default height in pixels of the Images that this reader will produce. + * @param format The format of the Image that this reader will produce. This must be one of the + * AIMAGE_FORMAT_* enum value defined in {@link AIMAGE_FORMATS}. + * @param usage specifies how the consumer will access the AImage, using combination of the + * AHARDWAREBUFFER_USAGE flags described in {@link hardware_buffer.h}. + * Passing {@link AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN} is equivalent to calling + * {@link AImageReader_new} with the same parameters. + * + * Note that not all format and usage flag combination is supported by the {@link AImageReader}. + * Below are the combinations supported by the {@link AImageReader}. + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FormatCompatible usage flags
non-{@link AIMAGE_FORMAT_PRIVATE} formats defined in {@link NdkImage.h} + * {@link AHARDWAREBUFFER_USAGE_CPU_READ_RARELY} or + * {@link AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}
{@link AIMAGE_FORMAT_RGBA_8888}{@link AHARDWAREBUFFER_USAGE_VIDEO_ENCODE} or + * {@link AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE}, or combined
+ * + * Available since API level 26. + * + * @return + * + * @see AImage + * @see AImageReader_new + * @see AHardwareBuffer + */ + AImageReader_newWithUsage :: proc(width: i32, height: i32, format: AImageFormats, usage: u64, maxImages: i32, reader: ^^AImageReader) -> media_status_t --- + + /** + * Acquire the next {@link AImage} from the image reader's queue asynchronously. + * + *

AImageReader acquire method similar to {@link AImageReader_acquireNextImage} that takes an + * additional parameter for the sync fence. All other parameters and the return values are + * identical to those passed to {@link AImageReader_acquireNextImage}.

+ * + * Available since API level 26. + * + * @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the + * buffer is ready to consume. When synchronization fence is not needed, fence will be set + * to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall + * use syscalls such as \c poll(), \c epoll(), \c select() to wait for the + * fence fd to change status before attempting to access the {@link AImage} returned. + * + * @see sync.h + * @see sync_get_fence_info + */ + AImageReader_acquireNextImageAsync :: proc(reader: ^AImageReader, image: ^^AImage, acquireFenceFd: ^i32) -> media_status_t --- + + /** + * Acquire the latest {@link AImage} from the image reader's queue asynchronously, dropping older + * images. + * + *

AImageReader acquire method similar to {@link AImageReader_acquireLatestImage} that takes an + * additional parameter for the sync fence. All other parameters and the return values are + * identical to those passed to {@link AImageReader_acquireLatestImage}.

+ * + * Available since API level 26. + * + * @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the + * buffer is ready to consume. When synchronization fence is not needed, fence will be set + * to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall + * use syscalls such as \c poll(), \c epoll(), \c select() to wait for the + * fence fd to change status before attempting to access the {@link AImage} returned. + * + * @see sync.h + * @see sync_get_fence_info + */ + AImageReader_acquireLatestImageAsync :: proc(reader: ^AImageReader, image: ^^AImage, acquireFenceFd: ^i32) -> media_status_t --- + + + /** + * Set the onBufferRemoved listener of this image reader. + * + *

Note that calling this method will replace previously registered listeners.

+ * + * Available since API level 26. + * + * @param reader The image reader of interest. + * @param listener the {@link AImageReader_BufferRemovedListener} to be registered. Set this to + * NULL if application no longer needs to listen to buffer removed events. + * + * @return + * + * @see AImage_getHardwareBuffer + */ + AImageReader_setBufferRemovedListener :: proc(reader: ^AImageReader, listener: ^AImageReader_BufferRemovedListener) -> media_status_t --- +} diff --git a/media/NdkMediaCodec.odin b/media/NdkMediaCodec.odin new file mode 100644 index 0000000..7dcf41c --- /dev/null +++ b/media/NdkMediaCodec.odin @@ -0,0 +1,560 @@ +//+build android +package mediandk + +import android "../" + +foreign import mediandk "system:android" + +AMEDIACODEC_KEY_HDR10_PLUS_INFO: cstring // __INTRODUCED_IN(31); +AMEDIACODEC_KEY_LOW_LATENCY: cstring // __INTRODUCED_IN(31); +AMEDIACODEC_KEY_OFFSET_TIME: cstring // __INTRODUCED_IN(31); +AMEDIACODEC_KEY_REQUEST_SYNC_FRAME: cstring // __INTRODUCED_IN(31); +AMEDIACODEC_KEY_SUSPEND: cstring // __INTRODUCED_IN(31); +AMEDIACODEC_KEY_SUSPEND_TIME: cstring // __INTRODUCED_IN(31); +AMEDIACODEC_KEY_VIDEO_BITRATE: cstring // __INTRODUCED_IN(31); + + +AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG :: 2 +AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM :: 4 +AMEDIACODEC_BUFFER_FLAG_PARTIAL_FRAME :: 8 + +AMEDIACODEC_CONFIGURE_FLAG_ENCODE :: 1 +AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED :: -3 +AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED :: -2 +AMEDIACODEC_INFO_TRY_AGAIN_LATER :: -1 + +_off_t_compat :: i64 + +cryptoinfo_mode_t :: enum { + CLEAR = 0, + AES_CTR = 1, + AES_WV = 2, + AES_CBC = 3 +} + +AMediaCodec :: struct{} + +AMediaCodecBufferInfo :: struct { + offset: i32, + size: i32, + presentationTimeUs: i64, + flags: u32, +} + +AMediaCodecCryptoInfo :: struct{} + +AMediaCodecOnAsyncNotifyCallback :: struct { + onAsyncInputAvailable: AMediaCodecOnAsyncInputAvailable, + onAsyncOutputAvailable: AMediaCodecOnAsyncOutputAvailable, + onAsyncFormatChanged: AMediaCodecOnAsyncFormatChanged, + onAsyncError: AMediaCodecOnAsyncError, +} + +cryptoinfo_pattern_t :: struct { + encryptBlocks: i32, + skipBlocks: i32, +} + +/** + * Called when an input buffer becomes available. + * The specified index is the index of the available input buffer. + */ +AMediaCodecOnAsyncInputAvailable :: #type proc "c" (codec: ^AMediaCodec, userdata: rawptr, index: i32) +/** + * Called when an output buffer becomes available. + * The specified index is the index of the available output buffer. + * The specified bufferInfo contains information regarding the available output buffer. + */ +AMediaCodecOnAsyncOutputAvailable :: #type proc "c" (codec: ^AMediaCodec, userdata: rawptr, index: i32, bufferInfo: ^AMediaCodecBufferInfo) +/** + * Called when the output format has changed. + * The specified format contains the new output format. + */ +AMediaCodecOnAsyncFormatChanged :: #type proc "c" (codec: ^AMediaCodec, userdata: rawptr, format: ^AMediaFormat) +/** + * Called when the MediaCodec encountered an error. + * The specified actionCode indicates the possible actions that client can take, + * and it can be checked by calling AMediaCodecActionCode_isRecoverable or + * AMediaCodecActionCode_isTransient. If both AMediaCodecActionCode_isRecoverable() + * and AMediaCodecActionCode_isTransient() return false, then the codec error is fatal + * and the codec must be deleted. + * The specified detail may contain more detailed messages about this error. + */ +AMediaCodecOnAsyncError :: #type proc "c" ( + codec: ^AMediaCodec, + userdata: rawptr, + error: media_status_t, + actionCode: i32, + detail: cstring +) + +/** + * Called when an output frame has rendered on the output surface. + * + * \param codec The codec object that generated this notification. + * \param userdata The user data set at AMediaCodec_setOnFrameRenderedCallback. + * \param mediaTimeUs The presentation time (media time) of the frame rendered. + * This is usually the same as specified in + * AMediaCodec_queueInputBuffer, but some codecs may alter + * the media time by applying some time-based transformation, + * such as frame rate conversion. In that case, presentation + * time corresponds to the actual output frame rendered. + * \param systemNano The system time when the frame was rendered. + */ +AMediaCodecOnFrameRendered :: #type proc "c" ( + codec: ^AMediaCodec, + userdata: rawptr, + mediaTimeUs: i64, + systemNano: i64, +) + +foreign mediandk { + /** + * Create codec by name. Use this if you know the exact codec you want to use. + * When configuring, you will need to specify whether to use the codec as an + * encoder or decoder. + * + * Available since API level 21. + */ + AMediaCodec_createCodecByName :: proc(name: cstring) -> ^AMediaCodec --- + + /** + * Create codec by mime type. Most applications will use this, specifying a + * mime type obtained from media extractor. + * + * Available since API level 21. + */ + AMediaCodec_createDecoderByType :: proc(mime_type: cstring) -> ^AMediaCodec --- + + /** + * Create encoder by name. + * + * Available since API level 21. + */ + AMediaCodec_createEncoderByType :: proc(mime_type: cstring) -> ^AMediaCodec --- + + /** + * Delete the codec and free its resources. + * + * Available since API level 21. + */ + AMediaCodec_delete :: proc(codec: ^AMediaCodec) -> media_status_t --- + + /** + * Configure the codec. For decoding you would typically get the format from an extractor. + * + * Available since API level 21. + */ + AMediaCodec_configure :: proc(coded: ^AMediaCodec, format: ^AMediaFormat, surface: ^android.ANativeWindow, crypto: ^AMediaCrypto, flags: u32) -> media_status_t --- + + /** + * Start the codec. A codec must be configured before it can be started, and must be started + * before buffers can be sent to it. + * + * Available since API level 21. + */ + AMediaCodec_start :: proc(codec: ^AMediaCodec) -> media_status_t --- + + /** + * Stop the codec. + * + * Available since API level 21. + */ + AMediaCodec_stop :: proc(codec: ^AMediaCodec) -> media_status_t --- + + /* + * Flush the codec's input and output. All indices previously returned from calls to + * AMediaCodec_dequeueInputBuffer and AMediaCodec_dequeueOutputBuffer become invalid. + * + * Available since API level 21. + */ + AMediaCodec_flush :: proc(codec: ^AMediaCodec) -> media_status_t --- + + /** + * Get an input buffer. The specified buffer index must have been previously obtained from + * dequeueInputBuffer, and not yet queued. + * + * Available since API level 21. + */ + AMediaCodec_getInputBuffer :: proc(codec: ^AMediaCodec, idx: uint, out_size: ^uint) -> [^]byte --- + + /** + * Get an output buffer. The specified buffer index must have been previously obtained from + * dequeueOutputBuffer, and not yet queued. + * + * Available since API level 21. + */ + AMediaCodec_getOutputBuffer :: proc(codec: ^AMediaCodec, idx: uint, out_size: ^uint) -> [^]byte --- + + /** + * Get the index of the next available input buffer. An app will typically use this with + * getInputBuffer() to get a pointer to the buffer, then copy the data to be encoded or decoded + * into the buffer before passing it to the codec. + * + * Available since API level 21. + */ + AMediaCodec_dequeueInputBuffer :: proc(codec: ^AMediaCodec, timeoutUs: i64) -> int --- + + + /** + * Send the specified buffer to the codec for processing. + * + * Available since API level 21. + */ + AMediaCodec_queueInputBuffer :: proc( + codec: ^AMediaCodec, + idx: uint, + offset: _off_t_compat, + size: uint, + time: u64, + flags: u32) -> media_status_t --- + + /** + * Send the specified buffer to the codec for processing. + * + * Available since API level 21. + */ + AMediaCodec_queueSecureInputBuffer :: proc( + codec: ^AMediaCodec, + idx: uint, + offset: _off_t_compat, + crypto_info: ^AMediaCodecCryptoInfo, + time: u64, + flags: u32) -> media_status_t --- + + /** + * Get the index of the next available buffer of processed data. + * + * Available since API level 21. + */ + AMediaCodec_dequeueOutputBuffer :: proc(codec: ^AMediaCodec, info: ^AMediaCodecBufferInfo, timeoutUs: i64) -> int --- + + /** + * Returns the format of the codec's output. + * The caller must free the returned format. + * + * Available since API level 21. + */ + AMediaCodec_getOutputFormat :: proc(codec: ^AMediaCodec) -> ^AMediaFormat --- + + /** + * 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. + * + * Available since API level 21. + */ + AMediaCodec_releaseOutputBuffer :: proc(codec: ^AMediaCodec, idx: uint, render: bool) -> media_status_t --- + + /** + * Dynamically sets the output surface of a codec. + * + * This can only be used if the codec was configured with an output surface. The + * new output surface should have a compatible usage type to the original output surface. + * E.g. codecs may not support switching from a SurfaceTexture (GPU readable) output + * to ImageReader (software readable) output. + * + * For more details, see the Java documentation for MediaCodec.setOutputSurface. + * + * Available since API level 21. + */ + AMediaCodec_setOutputSurface :: proc(codec: ^AMediaCodec, surface: ^android.ANativeWindow) -> media_status_t --- + + /** + * 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. + * + * Available since API level 21. + */ + AMediaCodec_releaseOutputBufferAtTime :: proc(mData: ^AMediaCodec, idx: uint, timestampNs: i64) -> media_status_t --- + + /** + * Creates a Surface that can be used as the input to encoder, in place of input buffers + * + * This can only be called after the codec has been configured via + * AMediaCodec_configure(..) and before AMediaCodec_start() has been called. + * + * The application is responsible for releasing the surface by calling + * ANativeWindow_release() when done. + * + * For more details, see the Java documentation for MediaCodec.createInputSurface. + * + * Available since API level 26. + */ + AMediaCodec_createInputSurface :: proc(mData: ^AMediaCodec, surface: ^^android.ANativeWindow) -> media_status_t --- + + /** + * Creates a persistent Surface that can be used as the input to encoder + * + * Persistent surface can be reused by MediaCodec instances and can be set + * on a new instance via AMediaCodec_setInputSurface(). + * A persistent surface can be connected to at most one instance of MediaCodec + * at any point in time. + * + * The application is responsible for releasing the surface by calling + * ANativeWindow_release() when done. + * + * For more details, see the Java documentation for MediaCodec.createPersistentInputSurface. + * + * Available since API level 26. + */ + AMediaCodec_createPersistentInputSurface :: proc(surface: ^^android.ANativeWindow) -> media_status_t --- + + /** + * Set a persistent-surface that can be used as the input to encoder, in place of input buffers + * + * The surface provided *must* be a persistent surface created via + * AMediaCodec_createPersistentInputSurface() + * This can only be called after the codec has been configured by calling + * AMediaCodec_configure(..) and before AMediaCodec_start() has been called. + * + * For more details, see the Java documentation for MediaCodec.setInputSurface. + * + * Available since API level 26. + */ + AMediaCodec_setInputSurface :: proc(mData: ^AMediaCodec, surface: ^android.ANativeWindow) -> media_status_t --- + + /** + * Signal additional parameters to the codec instance. + * + * Parameters can be communicated only when the codec is running, i.e + * after AMediaCodec_start() has been called. + * + * NOTE: Some of these parameter changes may silently fail to apply. + * + * Available since API level 26. + */ + AMediaCodec_setParameters :: proc(mData: ^AMediaCodec, params: ^AMediaFormat) -> media_status_t --- + + /** + * Signals end-of-stream on input. Equivalent to submitting an empty buffer with + * AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM set. + * + * Returns AMEDIA_ERROR_INVALID_OPERATION when used with an encoder not in executing state + * or not receiving input from a Surface created by AMediaCodec_createInputSurface or + * AMediaCodec_createPersistentInputSurface. + * + * Returns the previous codec error if one exists. + * + * Returns AMEDIA_OK when completed succesfully. + * + * For more details, see the Java documentation for MediaCodec.signalEndOfInputStream. + * + * Available since API level 26. + */ + AMediaCodec_signalEndOfInputStream :: proc(mData: ^AMediaCodec) -> media_status_t --- + + /** + * Get format of the buffer. The specified buffer index must have been previously obtained from + * dequeueOutputBuffer. + * The caller must free the returned format. + * + * Available since API level 28. + */ + AMediaCodec_getBufferFormat :: proc(codec: ^AMediaCodec, index: uint) -> ^AMediaFormat --- + + /** + * Get the component name. If the codec was created by createDecoderByType + * or createEncoderByType, what component is chosen is not known beforehand. + * Caller shall call AMediaCodec_releaseName to free the returned pointer. + * + * Available since API level 28. + */ + AMediaCodec_getName :: proc(codec: ^AMediaCodec, out_name: ^cstring) -> media_status_t --- + + /** + * Free the memory pointed by name which is returned by AMediaCodec_getName. + * + * Available since API level 28. + */ + AMediaCodec_releaseName :: proc(codec: ^AMediaCodec, name: cstring) --- + + /** + * Set an asynchronous callback for actionable AMediaCodec events. + * When asynchronous callback is enabled, it is an error for the client to call + * AMediaCodec_getInputBuffers(), AMediaCodec_getOutputBuffers(), + * AMediaCodec_dequeueInputBuffer() or AMediaCodec_dequeueOutputBuffer(). + * + * AMediaCodec_flush() behaves differently in asynchronous mode. + * After calling AMediaCodec_flush(), the client must call AMediaCodec_start() to + * "resume" receiving input buffers. Even if the client does not receive + * AMediaCodecOnAsyncInputAvailable callbacks from video encoders configured + * with an input surface, the client still needs to call AMediaCodec_start() + * to resume the input surface to send buffers to the encoders. + * + * When called with null callback, this method unregisters any previously set callback. + * + * Refer to the definition of AMediaCodecOnAsyncNotifyCallback on how each + * callback function is called and what are specified. + * The specified userdata is opaque data which will be passed along + * when the callback functions are called. MediaCodec does not look at or alter the + * value of userdata. Often it is a pointer to a client-owned object, + * and client manages the lifecycle of the object in that case. + * + * Once the callback is unregistered or the codec is reset / released, the + * previously registered callback will not be called. + * + * All callbacks are fired on one NDK internal thread. + * AMediaCodec_setAsyncNotifyCallback should not be called on the callback thread. + * No heavy duty task should be performed on callback thread. + * + * Available since API level 28. + */ + AMediaCodec_setAsyncNotifyCallback :: proc( + codec: ^AMediaCodec, + callback: AMediaCodecOnAsyncNotifyCallback, + userdata: rawptr) -> media_status_t --- + + /** + * Registers a callback to be invoked when an output frame is rendered on the output surface. + * + * This method can be called in any codec state, but will only have an effect in the + * Executing state for codecs that render buffers to the output surface. + * + * This callback is for informational purposes only: to get precise + * render timing samples, and can be significantly delayed and batched. Some frames may have + * been rendered even if there was no callback generated. + * + * When called with null callback, this method unregisters any previously set callback. + * + * Refer to the definition of AMediaCodecOnFrameRendered on how each + * callback function is called and what are specified. + * The specified userdata is opaque data which will be passed along + * when the callback functions are called. MediaCodec does not look at or alter the + * value of userdata. Often it is a pointer to a client-owned object, + * and client manages the lifecycle of the object in that case. + * + * Once the callback is unregistered or the codec is reset / released, the + * previously registered callback will not be called. + * + * All callbacks are fired on one NDK internal thread. + * AMediaCodec_setOnFrameRenderedCallback should not be called on the callback thread. + * No heavy duty task should be performed on callback thread. + * + * Available since Android T. + */ + AMediaCodec_setOnFrameRenderedCallback :: proc( + codec: ^AMediaCodec, + callback: AMediaCodecOnFrameRendered, + userdata: rawptr) -> media_status_t --- + + /** + * Release the crypto if applicable. + * + * Available since API level 28. + */ + AMediaCodec_releaseCrypto :: proc(codec: ^AMediaCodec) -> media_status_t --- + + /** + * Call this after AMediaCodec_configure() returns successfully to get the input + * format accepted by the codec. Do this to determine what optional configuration + * parameters were supported by the codec. + * The caller must free the returned format. + * + * Available since API level 28. + */ + AMediaCodec_getInputFormat :: proc(codec: ^AMediaCodec) -> ^AMediaFormat --- + + /** + * Returns true if the codec cannot proceed further, but can be recovered by stopping, + * configuring, and starting again. + * + * Available since API level 28. + */ + AMediaCodecActionCode_isRecoverable :: proc(actionCode: i32) -> bool --- + + /** + * Returns true if the codec error is a transient issue, perhaps due to + * resource constraints, and that the method (or encoding/decoding) may be + * retried at a later time. + * + * Available since API level 28. + */ + AMediaCodecActionCode_isTransient :: proc(actionCode: i32) -> bool --- + + /** + * 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". + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_new :: proc( + numsubsamples: i32, + key: [16]byte, + iv: [16]byte, + mode: cryptoinfo_mode_t, + clearbytes: ^uint, + encryptedbytes: ^uint) -> ^AMediaCodecCryptoInfo --- + + /** + * Delete an AMediaCodecCryptoInfo created previously with AMediaCodecCryptoInfo_new, or + * obtained from AMediaExtractor. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_delete :: proc(info: ^AMediaCodecCryptoInfo) -> media_status_t --- + + /** + * Set the crypto pattern on an AMediaCryptoInfo object. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_setPattern :: proc(info: ^AMediaCodecCryptoInfo, pattern: ^cryptoinfo_pattern_t) --- + + /** + * The number of subsamples that make up the buffer's contents. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_getNumSubSamples :: proc(info: ^AMediaCodecCryptoInfo) -> uint --- + + /** + * A 16-byte opaque key. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_getKey :: proc(info: ^AMediaCodecCryptoInfo, dst: [^]byte) -> media_status_t --- + + /** + * A 16-byte initialization vector. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_getIV :: proc(info: ^AMediaCodecCryptoInfo, dst: [^]byte) -> media_status_t --- + + /** + * The type of encryption that has been applied, + * one of AMEDIACODECRYPTOINFO_MODE_CLEAR or AMEDIACODECRYPTOINFO_MODE_AES_CTR. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_getMode :: proc(info: ^AMediaCodecCryptoInfo) -> cryptoinfo_mode_t --- + + /** + * The number of leading unencrypted bytes in each subsample. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_getClearBytes :: proc(info: ^AMediaCodecCryptoInfo, dst: ^uint) -> media_status_t --- + + /** + * The number of trailing encrypted bytes in each subsample. + * + * Available since API level 21. + */ + AMediaCodecCryptoInfo_getEncryptedBytes :: proc(info: ^AMediaCodecCryptoInfo, dst: ^uint) -> media_status_t --- +} diff --git a/media/NdkMediaCrypto.odin b/media/NdkMediaCrypto.odin new file mode 100644 index 0000000..fc59741 --- /dev/null +++ b/media/NdkMediaCrypto.odin @@ -0,0 +1,29 @@ +//+build android +package mediandk + +foreign import mediandk "system:mediandk" + +AMediaCrypto :: struct{} +AMediaUUID :: [16]u8 + +foreign mediandk { + /** + * Available since API level 21. + */ + AMediaCrypto_isCryptoSchemeSupported :: proc(uuid: AMediaUUID) -> bool --- + + /** + * Available since API level 21. + */ + AMediaCrypto_requiresSecureDecoderComponent :: proc(mime: cstring) -> bool --- + + /** + * Available since API level 21. + */ + AMediaCrypto_new :: proc(uuid: AMediaUUID, initData: rawptr, initDataSize: uint) -> ^AMediaCrypto --- + + /** + * Available since API level 21. + */ + AMediaCrypto_delete :: proc(crypto: ^AMediaCrypto) --- +} diff --git a/media/NdkMediaDataSource.odin b/media/NdkMediaDataSource.odin new file mode 100644 index 0000000..ba8b106 --- /dev/null +++ b/media/NdkMediaDataSource.odin @@ -0,0 +1,164 @@ +//+build android +package mediandk + +import "../" + +foreign import mediandk "system:mediandk" + +AMediaDataSource :: struct{} + +/* + * AMediaDataSource's callbacks will be invoked on an implementation-defined thread + * or thread pool. No guarantees are provided about which thread(s) will be used for + * callbacks. For example, |close| can be invoked from a different thread than the + * thread invoking |readAt|. As such, the Implementations of AMediaDataSource callbacks + * must be threadsafe. + */ + +/** + * Called to request data from the given |offset|. + * + * Implementations should should write up to |size| bytes into + * |buffer|, and return the number of bytes written. + * + * Return 0 if size is zero (thus no bytes are read). + * + * Return -1 to indicate that end of stream is reached. + */ +AMediaDataSourceReadAt :: #type proc "c" (userdata: rawptr, offset: android.off64_t, buffer: rawptr, size: uint) -> int + +/** + * Called to get the size of the data source. + * + * Return the size of data source in bytes, or -1 if the size is unknown. + */ +AMediaDataSourceGetSize :: #type proc "c" (userdata: rawptr) -> int + +/** + * Called to close the data source, unblock reads, and release associated + * resources. + * + * The NDK media framework guarantees that after the first |close| is + * called, no future callbacks will be invoked on the data source except + * for |close| itself. + * + * Closing a data source allows readAt calls that were blocked waiting + * for I/O data to return promptly. + * + * When using AMediaDataSource as input to AMediaExtractor, closing + * has the effect of unblocking slow reads inside of setDataSource + * and readSampleData. + */ +AMediaDataSourceClose :: #type proc "c" (userdata: rawptr) + +/** + * Called to get an estimate of the number of bytes that can be read from this data source + * starting at |offset| without blocking for I/O. + * + * Return -1 when such an estimate is not possible. + */ +AMediaDataSourceGetAvailableSize :: #type proc "c" (userdata: rawptr, offset: android.off64_t) -> int + + +foreign mediandk { + /** + * Create new media data source. Returns NULL if memory allocation + * for the new data source object fails. + * + * Available since API level 28. + */ + AMediaDataSource_new :: proc() -> ^AMediaDataSource --- + + /** + * Create new media data source. Returns NULL if memory allocation + * for the new data source object fails. + * + * Set the |uri| from which the data source will read, + * plus additional http headers when initiating the request. + * + * Headers will contain corresponding items from |key_values| + * in the following fashion: + * + * key_values[0]:key_values[1] + * key_values[2]:key_values[3] + * ... + * key_values[(numheaders - 1) * 2]:key_values[(numheaders - 1) * 2 + 1] + * + * Available since API level 29. + */ + AMediaDataSource_newUri :: proc(uri: cstring, numheaders: i32, key_values: ^[^]u8) -> ^AMediaDataSource --- + + /** + * Delete a previously created media data source. + * + * Available since API level 28. + */ + AMediaDataSource_delete :: proc(ds: ^AMediaDataSource) --- + + /** + * Set an user provided opaque handle. This opaque handle is passed as + * the first argument to the data source callbacks. + * + * Available since API level 28. + */ + AMediaDataSource_setUserdata :: proc(ds: ^AMediaDataSource, userdata: rawptr) --- + + /** + * Set a custom callback for supplying random access media data to the + * NDK media framework. + * + * Implement this if your app has special requirements for the way media + * data is obtained, or if you need a callback when data is read by the + * NDK media framework. + * + * Please refer to the definition of AMediaDataSourceReadAt for + * additional details. + * + * Available since API level 28. + */ + AMediaDataSource_setReadAt :: proc(ds: ^AMediaDataSource, cb: AMediaDataSourceReadAt) --- + + /** + * Set a custom callback for supplying the size of the data source to the + * NDK media framework. + * + * Please refer to the definition of AMediaDataSourceGetSize for + * additional details. + * + * Available since API level 28. + */ + AMediaDataSource_setGetSize :: proc(ds: ^AMediaDataSource, cb: AMediaDataSourceGetSize) --- + + /** + * Set a custom callback to receive signal from the NDK media framework + * when the data source is closed. + * + * Please refer to the definition of AMediaDataSourceClose for + * additional details. + * + * Available since API level 28. + */ + AMediaDataSource_setClose :: proc(ds: ^AMediaDataSource, cb: AMediaDataSourceClose) --- + + /** + * Close the data source, unblock reads, and release associated resources. + * + * Please refer to the definition of AMediaDataSourceClose for + * additional details. + * + * Available since API level 29. + */ + AMediaDataSource_close :: proc(ds: ^AMediaDataSource) --- + + /** + * Set a custom callback for supplying the estimated number of bytes + * that can be read from this data source starting at an offset without + * blocking for I/O. + * + * Please refer to the definition of AMediaDataSourceGetAvailableSize + * for additional details. + * + * Available since API level 29. + */ + AMediaDataSource_setGetAvailableSize :: proc(ds: ^AMediaDataSource, cb: AMediaDataSourceGetAvailableSize) --- +} diff --git a/media/NdkMediaDrm.odin b/media/NdkMediaDrm.odin new file mode 100644 index 0000000..0284a98 --- /dev/null +++ b/media/NdkMediaDrm.odin @@ -0,0 +1,658 @@ +//+build android +package mediandk + +foreign import mediandk "system:mediandk" + +/** +* String property name: identifies the maker of the DRM engine plugin +*/ +PROPERTY_VENDOR :: "vendor" + +/** +* String property name: identifies the version of the DRM engine plugin +*/ +PROPERTY_VERSION :: "version" + +/** +* String property name: describes the DRM engine plugin +*/ +PROPERTY_DESCRIPTION :: "description" + +/** +* String property name: a comma-separated list of cipher and mac algorithms +* supported by CryptoSession. The list may be empty if the DRM engine +* plugin does not support CryptoSession operations. +*/ +PROPERTY_ALGORITHMS :: "algorithms" + +/** +* Byte array property name: the device unique identifier is established during +* device provisioning and provides a means of uniquely identifying each device. +*/ +PROPERTY_DEVICE_UNIQUE_ID :: "deviceUniqueId" + +AMediaDrm :: struct{} + +AMediaDrmByteArray :: struct { + ptr: [^]byte, + length: uint, +} + +AMediaDrmSessionId :: AMediaDrmByteArray +AMediaDrmScope :: AMediaDrmByteArray +AMediaDrmKeySetId :: AMediaDrmByteArray +AMediaDrmSecureStop :: AMediaDrmByteArray +AMediaDrmKeyId :: AMediaDrmByteArray + +AMediaDrmEventType :: enum { + /** + * This event type indicates that the app needs to request a certificate from + * the provisioning server. The request message data is obtained using + * AMediaDrm_getProvisionRequest. + */ + PROVISION_REQUIRED = 1, + + /** + * This event type indicates that the app needs to request keys from a license + * server. The request message data is obtained using AMediaDrm_getKeyRequest. + */ + KEY_REQUIRED = 2, + + /** + * This event type indicates that the licensed usage duration for keys in a session + * has expired. The keys are no longer valid. + */ + KEY_EXPIRED = 3, + + /** + * This event may indicate some specific vendor-defined condition, see your + * DRM provider documentation for details + */ + VENDOR_DEFINED = 4, + + /** + * This event indicates that a session opened by the app has been reclaimed + * by the resource manager. + */ + SESSION_RECLAIMED = 5, +} + +AMediaDrmKeyType :: enum { + /** + * This key request type specifies that the keys will be for online use, they will + * not be saved to the device for subsequent use when the device is not connected + * to a network. + */ + STREAMING = 1, + + /** + * This key request type specifies that the keys will be for offline use, they + * will be saved to the device for use when the device is not connected to a network. + */ + OFFLINE = 2, + + /** + * This key request type specifies that previously saved offline keys should be released. + */ + RELEASE = 3 +} + +/** + * Introduced in API 33. + */ +AMediaDrmKeyRequestType :: enum i32 { + /** + * Key request type is initial license request. + * An initial license request is necessary to load keys. + */ + INITIAL, + + /** + * Key request type is license renewal. + * A renewal license request is necessary to prevent the keys from expiring. + */ + RENEWAL, + + /** + * Key request type is license release. + * A license release request indicates that keys are removed. + */ + RELEASE, + + /** + * Keys are already loaded and are available for use. No license request is necessary, and + * no key request data is returned. + */ + NONE, + + /** + * Keys have been loaded but an additional license request is needed + * to update their values. + */ + UPDATE +} + +/** + * Data type containing {key, value} pair + */ +AMediaDrmKeyValue :: struct { + mKey: cstring, + mValue: cstring, +} + +AMediaDrmKeyStatusType :: enum { + /** + * The key is currently usable to decrypt media data. + */ + USABLE, + + /** + * The key is no longer usable to decrypt media data because its expiration + * time has passed. + */ + EXPIRED, + + /** + * The key is not currently usable to decrypt media data because its output + * requirements cannot currently be met. + */ + OUTPUTNOTALLOWED, + + /** + * The status of the key is not yet known and is being determined. + */ + STATUSPENDING, + + /** + * The key is not currently usable to decrypt media data because of an + * internal error in processing unrelated to input parameters. + */ + INTERNALERROR, +} + +AMediaDrmKeyStatus :: struct { + keyId: AMediaDrmKeyId, + keyType: AMediaDrmKeyStatusType, +} + +AMediaDrmEventListener :: #type proc "c" (drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId, eventType: AMediaDrmEventType, extra: i32, data: [^]byte, dataSize: uint) + +AMediaDrmExpirationUpdateListener :: #type proc "c" (drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId, expiryTimeInMS: i64) + +AMediaDrmKeysChangeListener :: #type proc "c" (drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId, keyStatus: ^AMediaDrmKeyStatus, numKeys: uint, hasNewUsableKey: bool) + +foreign mediandk { + /** + * Query if the given scheme identified by its UUID is supported on this device, and + * whether the drm plugin is able to handle the media container format specified by mimeType. + * + * uuid identifies the universal unique ID of the crypto scheme. uuid must be 16 bytes. + * mimeType is the MIME type of the media container, e.g. "video/mp4". If mimeType + * is not known or required, it can be provided as NULL. + * + * Available since API level 21. + */ + AMediaDrm_isCryptoSchemeSupported :: proc(uuid: [^]byte, mimeType: cstring) -> bool --- + + /** + * Create a MediaDrm instance from a UUID. + * uuid identifies the universal unique ID of the crypto scheme. uuid must be 16 bytes. + * + * Available since API level 21. + */ + AMediaDrm_createByUUID :: proc(uuid: [^]byte) -> ^AMediaDrm --- + + /** + * Release a MediaDrm object. + * + * Available since API level 21. + */ + AMediaDrm_release :: proc(drm: ^AMediaDrm) --- + + /** + * Register a callback to be invoked when an event occurs. + * + * listener is the callback that will be invoked on event. + * + * Available since API level 21. + */ + AMediaDrm_setOnEventListener :: proc(drm: ^AMediaDrm, listener: AMediaDrmEventListener) -> media_status_t --- + + /** + * Register a callback to be invoked when an expiration update event occurs. + * + * listener is the callback that will be invoked on event. + * + * Available since API level 29. + */ + AMediaDrm_setOnExpirationUpdateListener :: proc(drm: ^AMediaDrm, listener: AMediaDrmExpirationUpdateListener) -> media_status_t --- + + /** + * Register a callback to be invoked when a key status change event occurs. + * + * listener is the callback that will be invoked on event. + * + * Available since API level 29. + */ + AMediaDrm_setOnKeysChangeListener :: proc(drm: ^AMediaDrm, listener: AMediaDrmKeysChangeListener) -> media_status_t --- + + /** + * Open a new session with the MediaDrm object. A session ID is returned. + * + * Returns AMEDIA_DRM_NOT_PROVISIONED if provisioning is needed. + * Returns AMEDIA_DRM_RESOURCE_BUSY if required resources are in use. + * + * Available since API level 21. + */ + AMediaDrm_openSession :: proc(drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId) -> media_status_t --- + + /** + * Close a session on the MediaDrm object that was previously opened + * with AMediaDrm_openSession. + * + * Available since API level 21. + */ + AMediaDrm_closeSession :: proc(drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId) -> media_status_t --- + + /** + * A key request/response exchange occurs between the app and a license server + * to obtain or release keys used to decrypt encrypted content. + * AMediaDrm_getKeyRequest is used to obtain an opaque key request byte array that + * is delivered to the license server. The opaque key request byte array is + * returned in *keyRequest and the number of bytes in the request is + * returned in *keyRequestSize. + * This API has same functionality as AMediaDrm_getKeyRequestWithDefaultUrlAndType() + * when defaultUrl and keyRequestType are passed in as NULL. + * + * After the app has received the key request response from the server, + * it should deliver to the response to the DRM engine plugin using the method + * AMediaDrm_provideKeyResponse. + * + * scope may be a sessionId or a keySetId, depending on the specified keyType. + * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set + * to the sessionId the keys will be provided to. When the keyType is + * KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys being released. + * Releasing keys from a device invalidates them for all sessions. + * + * init container-specific data, its meaning is interpreted based on the mime type + * provided in the mimeType parameter. It could contain, for example, the content + * ID, key ID or other data obtained from the content metadata that is required in + * generating the key request. init may be null when keyType is KEY_TYPE_RELEASE. + * + * initSize is the number of bytes of initData + * + * mimeType identifies the mime type of the content. + * + * keyType specifes the type of the request. The request may be to acquire keys for + * streaming or offline content, or to release previously acquired keys, which are + * identified by a keySetId. + * + * optionalParameters are included in the key request message to allow a client + * application to provide additional message parameters to the server. + * + * numOptionalParameters indicates the number of optional parameters provided + * by the caller + * + * On exit: + * If this returns AMEDIA_OK, + * 1. The keyRequest pointer will reference the opaque key request data. It + * will reside in memory owned by the AMediaDrm object, and will remain + * accessible until the next call to AMediaDrm_getKeyRequest + * or AMediaDrm_getKeyRequestWithDefaultUrlAndType or until the + * MediaDrm object is released. + * 2. keyRequestSize will be set to the size of the request + * If this does not return AMEDIA_OK, value of these parameters should not be used. + * + * Returns AMEDIA_DRM_NOT_PROVISIONED if reprovisioning is needed, due to a + * problem with the device certificate. + * + * Available since API level 21. + */ + AMediaDrm_getKeyRequest :: proc( + drm: ^AMediaDrm, + scope: ^AMediaDrmScope, + init: [^]byte, + initSize: uint, + mimeType: cstring, + keyType: AMediaDrmKeyType, + optionalParameters: [^]AMediaDrmKeyValue, + numOptionalParameters: uint, + keyRequest: ^[^]byte, + keyRequestSize: ^uint) -> media_status_t --- + + /** + * A key request/response exchange occurs between the app and a license server + * to obtain or release keys used to decrypt encrypted content. + * AMediaDrm_getKeyRequest is used to obtain an opaque key request byte array that + * is delivered to the license server. The opaque key request byte array is + * returned in *keyRequest and the number of bytes in the request is + * returned in *keyRequestSize. + * + * After the app has received the key request response from the server, + * it should deliver to the response to the DRM engine plugin using the method + * AMediaDrm_provideKeyResponse. + * + * scope may be a sessionId or a keySetId, depending on the specified keyType. + * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set + * to the sessionId the keys will be provided to. When the keyType is + * KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys being released. + * Releasing keys from a device invalidates them for all sessions. + * + * init container-specific data, its meaning is interpreted based on the mime type + * provided in the mimeType parameter. It could contain, for example, the content + * ID, key ID or other data obtained from the content metadata that is required in + * generating the key request. init may be null when keyType is KEY_TYPE_RELEASE. + * + * initSize is the number of bytes of initData + * + * mimeType identifies the mime type of the content. + * + * keyType specifes the type of the request. The request may be to acquire keys for + * streaming or offline content, or to release previously acquired keys, which are + * identified by a keySetId. + * + * optionalParameters are included in the key request message to allow a client + * application to provide additional message parameters to the server. + * + * numOptionalParameters indicates the number of optional parameters provided + * by the caller + * + * On exit: + * If this returns AMEDIA_OK, + * 1. The keyRequest pointer will reference the opaque key request data. It + * will reside in memory owned by the AMediaDrm object, and will remain + * accessible until the next call to either AMediaDrm_getKeyRequest + * or AMediaDrm_getKeyRequestWithDefaultUrlAndType or until the + * MediaDrm object is released. + * 2. keyRequestSize will be set to the size of the request. + * 3. defaultUrl will be set to the recommended URL to deliver the key request. + * The defaultUrl pointer will reference a NULL terminated URL string. + * It will be UTF-8 encoded and have same lifetime with the key request data + * KeyRequest pointer references to. Passing in NULL means you don't need it + * to be reported. + * 4. keyRequestType will be set to the key request type. Passing in NULL means + * you don't need it to be reported. + * + * Returns AMEDIA_DRM_NOT_PROVISIONED if reprovisioning is needed, due to a + * problem with the device certificate. + * + * Available since API level 33. + */ + AMediaDrm_getKeyRequestWithDefaultUrlAndType :: proc( + drm: ^AMediaDrm, + scope: ^AMediaDrmScope, + init: [^]byte, + initSize: uint, + mimeType: cstring, + keyType: AMediaDrmKeyType, + optionalParameters: [^]AMediaDrmKeyValue, + numOptionalParameters: uint, + keyRequest: ^[^]byte, + keyRequestSize: ^uint, + defaultUrl: ^cstring, + keyRequestType: ^AMediaDrmKeyRequestType) -> media_status_t --- + + /** + * A key response is received from the license server by the app, then it is + * provided to the DRM engine plugin using provideKeyResponse. When the + * response is for an offline key request, a keySetId is returned that can be + * used to later restore the keys to a new session with AMediaDrm_restoreKeys. + * When the response is for a streaming or release request, a null keySetId is + * returned. + * + * scope may be a sessionId or keySetId depending on the type of the + * response. Scope should be set to the sessionId when the response is for either + * streaming or offline key requests. Scope should be set to the keySetId when + * the response is for a release request. + * + * response points to the opaque response from the server + * responseSize should be set to the size of the response in bytes + * + * Available since API level 21. + */ + AMediaDrm_provideKeyResponse :: proc( + drm: ^AMediaDrm, + scope: ^AMediaDrmScope, + response: [^]byte, + responseSize: uint, + keySetId: ^AMediaDrmKeySetId) -> media_status_t --- + + /** + * Restore persisted offline keys into a new session. keySetId identifies the + * keys to load, obtained from a prior call to AMediaDrm_provideKeyResponse. + * + * sessionId is the session ID for the DRM session. + * keySetId identifies the saved key set to restore. + * + * Available since API level 21. + */ + AMediaDrm_restoreKeys :: proc(drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId, keySetId: ^AMediaDrmKeySetId) -> media_status_t --- + + /** + * Remove the current keys from a session. + * + * keySetId identifies keys to remove. + * + * Available since API level 21. + */ + AMediaDrm_removeKeys :: proc(drm: ^AMediaDrm, keySetId: ^AMediaDrmSessionId) -> media_status_t --- + + /** + * Request an informative description of the key status for the session. The status is + * in the form of {key, value} pairs. Since DRM license policies vary by vendor, + * the specific status field names are determined by each DRM vendor. Refer to your + * DRM provider documentation for definitions of the field names for a particular + * DRM engine plugin. + * + * On entry, numPairs should be set by the caller to the maximum number of pairs + * that can be returned (the size of the array). On exit, numPairs will be set + * to the number of entries written to the array. If the number of {key, value} pairs + * to be returned is greater than *numPairs, AMEDIA_DRM_SHORT_BUFFER will be returned + * and numPairs will be set to the number of pairs available. + * + * Available since API level 21. + */ + AMediaDrm_queryKeyStatus :: proc(drm: ^AMediaDrm, sessionId: ^AMediaDrmSessionId, keyValuePairs: [^]AMediaDrmKeyValue, numPairs: ^uint) -> media_status_t --- + + + /** + * A provision request/response exchange occurs between the app and a provisioning + * server to retrieve a device certificate. If provisionining is required, the + * EVENT_PROVISION_REQUIRED event will be sent to the event handler. + * getProvisionRequest is used to obtain the opaque provision request byte array that + * should be delivered to the provisioning server. + * On exit: + * 1. The provision request data will be referenced by provisionRequest, in + * memory owned by the AMediaDrm object. It will remain accessible until the + * next call to getProvisionRequest. + * 2. provisionRequestSize will be set to the size of the request data. + * 3. serverUrl will reference a NULL terminated string containing the URL + * the provisioning request should be sent to. It will remain accessible until + * the next call to getProvisionRequest. + * + * Available since API level 21. + */ + AMediaDrm_getProvisionRequest :: proc(drm: ^AMediaDrm, provisionRequest: ^[^]byte, provisionRequestSize: ^uint, serverUrl: ^cstring) -> media_status_t --- + + /** + * After a provision response is received by the app, it is provided to the DRM + * engine plugin using this method. + * + * response is the opaque provisioning response byte array to provide to the + * DRM engine plugin. + * responseSize is the length of the provisioning response in bytes. + * + * Returns AMEDIA_DRM_DEVICE_REVOKED if the response indicates that the + * server rejected the request + * + * Available since API level 21. + */ + AMediaDrm_provideProvisionResponse :: proc(drm: ^AMediaDrm, response: [^]byte, responseSize: uint) -> media_status_t --- + + /** + * A means of enforcing limits on the number of concurrent streams per subscriber + * across devices is provided via SecureStop. This is achieved by securely + * monitoring the lifetime of sessions. + * + * Information from the server related to the current playback session is written + * to persistent storage on the device when each MediaCrypto object is created. + * + * In the normal case, playback will be completed, the session destroyed and the + * Secure Stops will be queried. The app queries secure stops and forwards the + * secure stop message to the server which verifies the signature and notifies the + * server side database that the session destruction has been confirmed. The persisted + * record on the client is only removed after positive confirmation that the server + * received the message using releaseSecureStops(). + * + * numSecureStops is set by the caller to the maximum number of secure stops to + * return. On exit, *numSecureStops will be set to the number actually returned. + * If *numSecureStops is too small for the number of secure stops available, + * AMEDIA_DRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the + * number required. + * + * Available since API level 21. + */ + AMediaDrm_getSecureStops :: proc(drm: ^AMediaDrm, secureStops: ^AMediaDrmSecureStop, numSecureStops: ^uint) -> media_status_t --- + + /** + * Process the SecureStop server response message ssRelease. After authenticating + * the message, remove the SecureStops identified in the response. + * + * ssRelease is the server response indicating which secure stops to release + * + * Available since API level 21. + */ + AMediaDrm_releaseSecureStops :: proc(drm: ^AMediaDrm, ssRelease: ^AMediaDrmSecureStop) -> media_status_t --- + + /** + * Read a DRM engine plugin String property value, given the property name string. + * + * propertyName identifies the property to query + * On return, propertyValue will be set to point to the property value. The + * memory that the value resides in is owned by the NDK MediaDrm API and + * will remain valid until the next call to AMediaDrm_getPropertyString. + * + * Available since API level 21. + */ + AMediaDrm_getPropertyString :: proc(drm: ^AMediaDrm, propertyName: cstring, propertyValue: ^cstring) -> media_status_t --- + + /** + * Read a DRM engine plugin byte array property value, given the property name string. + * On return, *propertyValue will be set to point to the property value. The + * memory that the value resides in is owned by the NDK MediaDrm API and + * will remain valid until the next call to AMediaDrm_getPropertyByteArray. + * + * Available since API level 21. + */ + AMediaDrm_getPropertyByteArray :: proc(drm: ^AMediaDrm, propertyName: cstring, propertyValue: ^AMediaDrmByteArray) -> media_status_t --- + + /** + * Set a DRM engine plugin String property value. + * + * Available since API level 21. + */ + AMediaDrm_setPropertyString :: proc(drm: ^AMediaDrm, propertyName: cstring, value: cstring) -> media_status_t --- + + /** + * Set a DRM engine plugin byte array property value. + * + * Available since API level 21. + */ + AMediaDrm_setPropertyByteArray :: proc(drm: ^AMediaDrm, propertyName: cstring, value: [^]byte, valueSize: uint) -> media_status_t --- + + /** + * In addition to supporting decryption of DASH Common Encrypted Media, the + * MediaDrm APIs provide the ability to securely deliver session keys from + * an operator's session key server to a client device, based on the factory-installed + * root of trust, and then perform encrypt, decrypt, sign and verify operations + * with the session key on arbitrary user data. + * + * Operators create session key servers that receive session key requests and provide + * encrypted session keys which can be used for general purpose crypto operations. + * + * Generic encrypt/decrypt/sign/verify methods are based on the established session + * keys. These keys are exchanged using the getKeyRequest/provideKeyResponse methods. + * + * Applications of this capability include securing various types of purchased or + * private content, such as applications, books and other media, photos or media + * delivery protocols. + */ + + /* + * Encrypt the data referenced by input of length dataSize using algorithm specified + * by cipherAlgorithm, and write the encrypted result into output. The caller must + * ensure that the output buffer is large enough to accept dataSize bytes. The key + * to use is identified by the 16 byte keyId. The key must have been loaded into + * the session using provideKeyResponse. + * + * Available since API level 21. + */ + AMediaDrm_encrypt :: proc( + drm: ^AMediaDrm, + sessionId: ^AMediaDrmSessionId, + cipherAlgorithm: cstring, + keyId: [^]byte, + iv: [^]byte, + input: [^]byte, + output: [^]byte, + dataSize: uint) -> media_status_t --- + + /* + * Decrypt the data referenced by input of length dataSize using algorithm specified + * by cipherAlgorithm, and write the decrypted result into output. The caller must + * ensure that the output buffer is large enough to accept dataSize bytes. The key + * to use is identified by the 16 byte keyId. The key must have been loaded into + * the session using provideKeyResponse. + * + * Available since API level 21. + */ + AMediaDrm_decrypt :: proc( + drm: ^AMediaDrm, + sessionId: ^AMediaDrmSessionId, + cipherAlgorithm: cstring, + keyId: [^]byte, + iv: [^]byte, + input: [^]byte, + output: [^]byte, + dataSize: uint) -> media_status_t --- + + /* + * Generate a signature using the specified macAlgorithm over the message data + * referenced by message of size messageSize and store the signature in the + * buffer referenced signature of max size *signatureSize. If the buffer is not + * large enough to hold the signature, AMEDIA_DRM_SHORT_BUFFER is returned and + * *signatureSize is set to the buffer size required. The key to use is identified + * by the 16 byte keyId. The key must have been loaded into the session using + * provideKeyResponse. + * + * Available since API level 21. + */ + AMediaDrm_sign :: proc( + drm: ^AMediaDrm, + sessionId: ^AMediaDrmSessionId, + macAlgorithm: cstring, + keyId: [^]byte, + message: [^]byte, + messageSize: uint, + signature: [^]byte, + signatureSize: ^uint) -> media_status_t --- + + /* + * Perform a signature verification using the specified macAlgorithm over the message + * data referenced by the message parameter of size messageSize. Returns AMEDIA_OK + * if the signature matches, otherwise MEDAIDRM_VERIFY_FAILED is returned. The key to + * use is identified by the 16 byte keyId. The key must have been loaded into the + * session using provideKeyResponse. + * + * Available since API level 21. + */ + AMediaDrm_verify :: proc( + drm: ^AMediaDrm, + sessionId: ^AMediaDrmSessionId, + macAlgorithm: cstring, + keyId: [^]byte, + message: [^]byte, + messageSize: uint, + signature: [^]byte, + signatureSize: uint) -> media_status_t --- +} diff --git a/media/NdkMediaError.odin b/media/NdkMediaError.odin new file mode 100644 index 0000000..5753cba --- /dev/null +++ b/media/NdkMediaError.odin @@ -0,0 +1,81 @@ +//+build android +package mediandk + +/** + * Media error message types returned from NDK media functions. + */ +media_status_t :: enum { + /** The requested media operation completed successfully. */ + AMEDIA_OK = 0, + + /** + * This indicates required resource was not able to be allocated. + */ + AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE = 1100, + + /** + * This indicates the resource manager reclaimed the media resource used by the codec. + * With this error, the codec must be released, as it has moved to terminal state. + */ + AMEDIACODEC_ERROR_RECLAIMED = 1101, + + AMEDIA_ERROR_BASE = -10000, + + /** The called media function failed with an unknown error. */ + AMEDIA_ERROR_UNKNOWN = AMEDIA_ERROR_BASE, + + /** The input media data is corrupt or incomplete. */ + AMEDIA_ERROR_MALFORMED = AMEDIA_ERROR_BASE - 1, + + /** The required operation or media formats are not supported. */ + AMEDIA_ERROR_UNSUPPORTED = AMEDIA_ERROR_BASE - 2, + + /** An invalid (or already closed) object is used in the function call. */ + AMEDIA_ERROR_INVALID_OBJECT = AMEDIA_ERROR_BASE - 3, + + /** At least one of the invalid parameters is used. */ + AMEDIA_ERROR_INVALID_PARAMETER = AMEDIA_ERROR_BASE - 4, + + /** The media object is not in the right state for the required operation. */ + AMEDIA_ERROR_INVALID_OPERATION = AMEDIA_ERROR_BASE - 5, + + /** Media stream ends while processing the requested operation. */ + AMEDIA_ERROR_END_OF_STREAM = AMEDIA_ERROR_BASE - 6, + + /** An Error occurred when the Media object is carrying IO operation. */ + AMEDIA_ERROR_IO = AMEDIA_ERROR_BASE - 7, + + /** The required operation would have to be blocked (on I/O or others), + * but blocking is not enabled. + */ + AMEDIA_ERROR_WOULD_BLOCK = AMEDIA_ERROR_BASE - 8, + + AMEDIA_DRM_ERROR_BASE = -20000, + AMEDIA_DRM_NOT_PROVISIONED = AMEDIA_DRM_ERROR_BASE - 1, + AMEDIA_DRM_RESOURCE_BUSY = AMEDIA_DRM_ERROR_BASE - 2, + AMEDIA_DRM_DEVICE_REVOKED = AMEDIA_DRM_ERROR_BASE - 3, + AMEDIA_DRM_SHORT_BUFFER = AMEDIA_DRM_ERROR_BASE - 4, + AMEDIA_DRM_SESSION_NOT_OPENED = AMEDIA_DRM_ERROR_BASE - 5, + AMEDIA_DRM_TAMPER_DETECTED = AMEDIA_DRM_ERROR_BASE - 6, + AMEDIA_DRM_VERIFY_FAILED = AMEDIA_DRM_ERROR_BASE - 7, + AMEDIA_DRM_NEED_KEY = AMEDIA_DRM_ERROR_BASE - 8, + AMEDIA_DRM_LICENSE_EXPIRED = AMEDIA_DRM_ERROR_BASE - 9, + + AMEDIA_IMGREADER_ERROR_BASE = -30000, + + /** There are no more image buffers to read/write image data. */ + AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE = AMEDIA_IMGREADER_ERROR_BASE - 1, + + /** The AImage object has used up the allowed maximum image buffers. */ + AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED = AMEDIA_IMGREADER_ERROR_BASE - 2, + + /** The required image buffer could not be locked to read. */ + AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE = AMEDIA_IMGREADER_ERROR_BASE - 3, + + /** The media data or buffer could not be unlocked. */ + AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE = AMEDIA_IMGREADER_ERROR_BASE - 4, + + /** The media/buffer needs to be locked to perform the required operation. */ + AMEDIA_IMGREADER_IMAGE_NOT_LOCKED = AMEDIA_IMGREADER_ERROR_BASE - 5, +} + diff --git a/media/NdkMediaExtractor.odin b/media/NdkMediaExtractor.odin new file mode 100644 index 0000000..793f3f7 --- /dev/null +++ b/media/NdkMediaExtractor.odin @@ -0,0 +1,213 @@ +//+build android +package mediandk + +import "../" + +foreign import mediandk "system:mediandk" + +SeekMode :: enum { + PREVIOUS_SYNC, + NEXT_SYNC, + CLOSEST_SYNC +} + +SampleFlags :: enum u32 { + SYNC = 1, + ENCRYPTED = 2, +} + +AMediaExtractor :: struct{} + +/** +* mapping of crypto scheme uuid to the scheme specific data for that scheme +*/ +PsshEntry :: struct { + uuid: AMediaUUID, + datalen: uint, + data: rawptr, +} + +/** +* list of crypto schemes and their data +*/ +PsshInfo :: struct { + numentries: uint, + entries: [0]PsshEntry, +} + +foreign mediandk { + /** + * Create new media extractor. + * + * Available since API level 21. + */ + AMediaExtractor_new :: proc() -> ^AMediaExtractor --- + + /** + * Delete a previously created media extractor. + * + * Available since API level 21. + */ + AMediaExtractor_delete :: proc(extractor: ^AMediaExtractor) -> media_status_t --- + + /** + * Set the file descriptor from which the extractor will read. + * + * Available since API level 21. + */ + AMediaExtractor_setDataSourceFd :: proc(extractor: ^AMediaExtractor, fd: i32, offset: android.off64_t, length: android.off64_t) -> media_status_t --- + + /** + * Set the URI from which the extractor will read. + * + * Available since API level 21. + */ + AMediaExtractor_setDataSource :: proc(extractor: ^AMediaExtractor, location: cstring) -> media_status_t --- + + /** + * Set the custom data source implementation from which the extractor will read. + * + * Available since API level 28. + */ + AMediaExtractor_setDataSourceCustom :: proc(extractor: ^AMediaExtractor, src: ^AMediaDataSource) -> media_status_t --- + + /** + * Return the number of tracks in the previously specified media file + * + * Available since API level 21. + */ + AMediaExtractor_getTrackCount :: proc(extractor: ^AMediaExtractor) -> uint --- + + /** + * Return the format of the specified track. The caller must free the returned format + * + * Available since API level 21. + */ + AMediaExtractor_getTrackFormat :: proc(extractor: ^AMediaExtractor, idx: uint) -> ^AMediaFormat --- + + /** + * Select the specified track. Subsequent calls to readSampleData, getSampleTrackIndex and + * getSampleTime only retrieve information for the subset of tracks selected. + * Selecting the same track multiple times has no effect, the track is + * only selected once. + * + * Available since API level 21. + */ + AMediaExtractor_selectTrack :: proc(extractor: ^AMediaExtractor, idx: uint) -> media_status_t --- + + /** + * Unselect the specified track. Subsequent calls to readSampleData, getSampleTrackIndex and + * getSampleTime only retrieve information for the subset of tracks selected. + * + * Available since API level 21. + */ + AMediaExtractor_unselectTrack :: proc(extractor: ^AMediaExtractor, idx: uint) -> media_status_t --- + + /** + * Read the current sample. + * + * Available since API level 21. + */ + AMediaExtractor_readSampleData :: proc(extractor: ^AMediaExtractor, buffer: [^]u8, capacity: uint) -> int --- + + /** + * Read the current sample's flags. + * + * Available since API level 21. + */ + AMediaExtractor_getSampleFlags :: proc(extractor: ^AMediaExtractor) -> SampleFlags --- + + /** + * Returns the track index the current sample originates from (or -1 + * if no more samples are available) + * + * Available since API level 21. + */ + AMediaExtractor_getSampleTrackIndex :: proc(extractor: ^AMediaExtractor) -> i32 --- + + /** + * Returns the current sample's presentation time in microseconds. + * or -1 if no more samples are available. + * + * Available since API level 21. + */ + AMediaExtractor_getSampleTime :: proc(extractor: ^AMediaExtractor) -> i64 --- + + /** + * Advance to the next sample. Returns false if no more sample data + * is available (end of stream). + * + * Available since API level 21. + */ + AMediaExtractor_advance :: proc(extractor: ^AMediaExtractor) -> bool --- + + + /** + * Available since API level 21. + */ + AMediaExtractor_seekTo :: proc(extractor: ^AMediaExtractor, seekPosUs: i64, mode: SeekMode) -> media_status_t --- + + /** + * Get the PSSH info if present. + * + * Available since API level 21. + */ + AMediaExtractor_getPsshInfo :: proc(extractor: ^AMediaExtractor) -> ^PsshInfo --- + + /** + * Available since API level 21. + */ + AMediaExtractor_getSampleCryptoInfo :: proc(extractor: ^AMediaExtractor) -> ^AMediaCodecCryptoInfo --- + + /** + * Returns the format of the extractor. The caller must free the returned format + * using AMediaFormat_delete(format). + * + * This function will always return a format however, the format could be empty + * (no key-value pairs) if the media container does not provide format information. + * + * Available since API level 28. + */ + AMediaExtractor_getFileFormat :: proc(extractor: ^AMediaExtractor) -> ^AMediaFormat --- + + /** + * Returns the size of the current sample in bytes, or -1 when no samples are + * available (end of stream). This API can be used in in conjunction with + * AMediaExtractor_readSampleData: + * + * ssize_t sampleSize = AMediaExtractor_getSampleSize(ex) + * uint8_t *buf = new uint8_t[sampleSize] + * AMediaExtractor_readSampleData(ex, buf, sampleSize) + * + * Available since API level 28. + */ + AMediaExtractor_getSampleSize :: proc(extractor: ^AMediaExtractor) -> int --- + + /** + * Returns the duration of cached media samples downloaded from a network data source + * (AMediaExtractor_setDataSource with a "http(s)" URI) in microseconds. + * + * This information is calculated using total bitrate if total bitrate is not in the + * media container it is calculated using total duration and file size. + * + * Returns -1 when the extractor is not reading from a network data source, or when the + * cached duration cannot be calculated (bitrate, duration, and file size information + * not available). + * + * Available since API level 28. + */ + AMediaExtractor_getCachedDuration :: proc(extractor: ^AMediaExtractor) -> i64 --- + + /** + * Read the current sample's metadata format into |fmt|. Examples of sample metadata are + * SEI (supplemental enhancement information) and MPEG user data, both of which can embed + * closed-caption data. + * + * Returns AMEDIA_OK on success or AMEDIA_ERROR_* to indicate failure reason. + * Existing key-value pairs in |fmt| would be removed if this API returns AMEDIA_OK. + * The contents of |fmt| is undefined if this API returns AMEDIA_ERROR_*. + * + * Available since API level 28. + */ + AMediaExtractor_getSampleFormat :: proc(ex: ^AMediaExtractor, fmt: ^AMediaFormat) -> media_status_t --- +} diff --git a/media/NdkMediaFormat.odin b/media/NdkMediaFormat.odin new file mode 100644 index 0000000..d33569e --- /dev/null +++ b/media/NdkMediaFormat.odin @@ -0,0 +1,306 @@ +//+build android +package mediandk + +foreign import mediandk "system:mediandk" + +AMediaFormat :: struct{} + +AMEDIAFORMAT_KEY_AAC_DRC_ATTENUATION_FACTOR: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AAC_DRC_BOOST_FACTOR: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AAC_DRC_HEAVY_COMPRESSION: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AAC_DRC_TARGET_REFERENCE_LEVEL: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AAC_ENCODED_TARGET_LEVEL: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AAC_PROFILE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_AAC_SBR_MODE: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_AUDIO_SESSION_ID: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_BITRATE_MODE: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_BIT_RATE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_CAPTURE_RATE: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_CHANNEL_COUNT: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_CHANNEL_MASK: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_COLOR_FORMAT: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_COLOR_RANGE: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_COLOR_STANDARD: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_COLOR_TRANSFER: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_COMPLEXITY: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_CSD: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_CSD_0: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_CSD_1: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_CSD_2: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_DISPLAY_CROP: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_DISPLAY_HEIGHT: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_DISPLAY_WIDTH: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_DURATION: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_FRAME_RATE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_GRID_COLUMNS: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_GRID_ROWS: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_HDR_STATIC_INFO: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_HEIGHT: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_IS_ADTS: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_IS_AUTOSELECT: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_IS_DEFAULT: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_I_FRAME_INTERVAL: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_LANGUAGE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_LATENCY: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_LEVEL: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_MAX_HEIGHT: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_MAX_INPUT_SIZE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_MAX_WIDTH: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_MIME: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_MPEG_USER_DATA: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_OPERATING_RATE: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_PCM_ENCODING: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_PRIORITY: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_PROFILE: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_ROTATION: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_SAMPLE_RATE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_SEI: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_SLICE_HEIGHT: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_STRIDE: cstring //__INTRODUCED_IN(21) +AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_TEMPORAL_LAYERING: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_TILE_HEIGHT: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_TILE_WIDTH: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_TIME_US: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_TRACK_ID: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_TRACK_INDEX: cstring //__INTRODUCED_IN(28) +AMEDIAFORMAT_KEY_WIDTH: cstring //__INTRODUCED_IN(21) + + +AMEDIAFORMAT_KEY_ALBUM: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ALBUMART: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ALBUMARTIST: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ARTIST: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_PRESENTATION_ID: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_PROGRAM_ID: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_AUTHOR: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_BITS_PER_SAMPLE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CDTRACKNUMBER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_COMPILATION: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_COMPOSER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CREATE_INPUT_SURFACE_SUSPENDED: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_IV: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_KEY: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_MODE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CSD_AVC: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_CSD_HEVC: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_D263: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_DATE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_DISCNUMBER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ENCODER_DELAY: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ENCODER_PADDING: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ESDS: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_EXIF_OFFSET: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_EXIF_SIZE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_FRAME_COUNT: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_GENRE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_ICC_PROFILE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_IS_SYNC_FRAME: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_LOCATION: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_LOOP: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_LYRICIST: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_MANUFACTURER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_MAX_BIT_RATE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_PSSH: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_SAR_HEIGHT: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_SAR_WIDTH: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_TARGET_TIME: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_THUMBNAIL_CSD_HEVC: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_THUMBNAIL_TIME: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_TITLE: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_VALID_SAMPLES: cstring //__INTRODUCED_IN(29) +AMEDIAFORMAT_KEY_YEAR: cstring //__INTRODUCED_IN(29) + +/** + * An optional key describing the low latency decoding mode. This is an optional parameter + * that applies only to decoders. If enabled, the decoder doesn't hold input and output + * data more than required by the codec standards. + * The associated value is an integer (0 or 1): 1 when low-latency decoding is enabled, + * 0 otherwise. The default value is 0. + * + * Available since API level 30. + */ +AMEDIAFORMAT_KEY_LOW_LATENCY: cstring //__INTRODUCED_IN(30) + +AMEDIAFORMAT_KEY_HDR10_PLUS_INFO: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_SLOW_MOTION_MARKERS: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_THUMBNAIL_CSD_AV1C: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_XMP_OFFSET: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_XMP_SIZE: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_SAMPLE_FILE_OFFSET: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_LAST_SAMPLE_INDEX_IN_CHUNK: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_KEY_SAMPLE_TIME_BEFORE_APPEND: cstring //__INTRODUCED_IN(31) + +AMEDIAFORMAT_KEY_PICTURE_TYPE: cstring //__INTRODUCED_IN(33) +AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL: cstring //__INTRODUCED_IN(33) +AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE: cstring //__INTRODUCED_IN(33) + +AMEDIAFORMAT_VIDEO_QP_B_MAX: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_B_MIN: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_I_MAX: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_I_MIN: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_MAX: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_MIN: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_P_MAX: cstring //__INTRODUCED_IN(31) +AMEDIAFORMAT_VIDEO_QP_P_MIN: cstring //__INTRODUCED_IN(31) + +/** + * MPEG-H audio profile and level compatibility. + * + * See FDAmd_2 of ISO_IEC_23008-3;2019 MHAProfileAndLevelCompatibilitySetBox. + * + * Available since API level 32. + */ +AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS: cstring //__INTRODUCED_IN(32) + +/** + * MPEG-H audio profile level indication. + * + * See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord mpegh3daProfileLevelIndication. + * + * Available since API level 32. + */ +AMEDIAFORMAT_KEY_MPEGH_PROFILE_LEVEL_INDICATION: cstring //__INTRODUCED_IN(32) + +/** + * MPEG-H audio reference channel layout. + * + * See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord referenceChannelLayout + * and ISO_IEC_23001‐8 ChannelConfiguration value. + * + * Available since API level 32. + */ +AMEDIAFORMAT_KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT: cstring //__INTRODUCED_IN(32) + +foreign mediandk { + /** + * Available since API level 21. + */ + AMediaFormat_new :: proc() -> ^AMediaFormat --- + + /** + * Available since API level 21. + */ + AMediaFormat_delete :: proc(format: ^AMediaFormat) -> media_status_t --- + + /** + * Human readable representation of the format. The returned string is owned by the format, + * and remains valid until the next call to toString, or until the format is deleted. + * + * Available since API level 21. + */ + AMediaFormat_toString :: proc(format: ^AMediaFormat) -> cstring --- + + /** + * Available since API level 21. + */ + AMediaFormat_getInt32 :: proc(format: ^AMediaFormat, name: cstring, out: ^i32) -> bool --- + /** + * Available since API level 21. + */ + AMediaFormat_getInt64 :: proc(format: ^AMediaFormat, name: cstring, out: ^i64) -> bool --- + /** + * Available since API level 21. + */ + AMediaFormat_getFloat :: proc(format: ^AMediaFormat, name: cstring, out: ^f32) -> bool --- + /** + * Available since API level 21. + */ + AMediaFormat_getSize :: proc(format: ^AMediaFormat, name: cstring, out: ^uint) -> bool --- + /** + * The returned data is owned by the format and remains valid as long as the named entry + * is part of the format. + * + * Available since API level 21. + */ + AMediaFormat_getBuffer :: proc(format: ^AMediaFormat, name: cstring, data: ^rawptr, size: ^uint) -> bool --- + /** + * The returned string is owned by the format, and remains valid until the next call to getString, + * or until the format is deleted. + * + * Available since API level 21. + */ + AMediaFormat_getString :: proc(format: ^AMediaFormat, name: cstring, out: ^cstring) -> bool --- + + /** + * Available since API level 21. + */ + AMediaFormat_setInt32 :: proc(format: ^AMediaFormat, name: cstring, value: i32) --- + /** + * Available since API level 21. + */ + AMediaFormat_setInt64 :: proc(format: ^AMediaFormat, name: cstring, value: i64) --- + /** + * Available since API level 21. + */ + AMediaFormat_setFloat :: proc(format: ^AMediaFormat, name: cstring, value: f32) --- + /** + * The provided string is copied into the format. + * + * Available since API level 21. + */ + AMediaFormat_setString :: proc(format: ^AMediaFormat, name: cstring, value: cstring) --- + /** + * The provided data is copied into the format. + * + * Available since API level 21. + */ + AMediaFormat_setBuffer :: proc(format: ^AMediaFormat, name: cstring, data: rawptr, size: uint) --- + + /** + * Available since API level 28. + */ + AMediaFormat_getDouble :: proc(format: ^AMediaFormat, name: cstring, out: ^f64) -> bool --- + /** + * Available since API level 28. + */ + AMediaFormat_getRect :: proc(format: ^AMediaFormat, name: cstring, left: ^i32, top: ^i32, right: ^i32, bottom: ^i32) -> bool --- + + /** + * Available since API level 28. + */ + AMediaFormat_setDouble :: proc(format: ^AMediaFormat, name: cstring, value: f64) --- + /** + * Available since API level 28. + */ + AMediaFormat_setSize :: proc(format: ^AMediaFormat, name: cstring, value: uint) --- + /** + * Available since API level 28. + */ + AMediaFormat_setRect :: proc(format: ^AMediaFormat, name: cstring, left: i32, top: i32, right: i32, bottom: i32) --- + + /** + * Remove all key/value pairs from the given AMediaFormat. + * + * Available since API level 29. + */ + AMediaFormat_clear :: proc(format: ^AMediaFormat) --- + + /** + * Copy one AMediaFormat to another. + * + * Available since API level 29. + */ + AMediaFormat_copy :: proc(to: ^AMediaFormat, from: ^AMediaFormat) -> media_status_t --- +} diff --git a/media/NdkMediaMuxer.odin b/media/NdkMediaMuxer.odin new file mode 100644 index 0000000..9f00094 --- /dev/null +++ b/media/NdkMediaMuxer.odin @@ -0,0 +1,146 @@ +//+build android +package mediandk + +foreign import mediandk "system:mediandk" + +OutputFormat :: enum i32 { + MPEG_4 = 0, + WEBM = 1, + THREE_GPP = 2, +} + +AppendMode :: enum i32 { + /* Last group of pictures(GOP) of video track can be incomplete, so it would be safe to + * scrap that and rewrite. If both audio and video tracks are present in a file, then + * samples of audio track after last GOP of video would be scrapped too. + * If only audio track is present, then no sample would be discarded. + */ + IGNORE_LAST_VIDEO_GOP = 0, + // Keep all existing samples as it is and append new samples after that only. + TO_EXISTING_DATA = 1, +} + +AMediaMuxer :: struct{} + +foreign mediandk { + /** + * Create new media muxer. + * + * Available since API level 21. + */ + AMediaMuxer_new :: proc(fd: i32, format: OutputFormat) -> ^AMediaMuxer --- + + /** + * Delete a previously created media muxer. + * + * Available since API level 21. + */ + AMediaMuxer_delete :: proc(muxer: ^AMediaMuxer) -> media_status_t --- + + /** + * 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]. + * + * Available since API level 21. + */ + AMediaMuxer_setLocation :: proc(muxer: ^AMediaMuxer, latitude: f32, longitude: f32) -> media_status_t --- + + /** + * 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. + * + * Available since API level 21. + */ + AMediaMuxer_setOrientationHint :: proc(muxer: ^AMediaMuxer, degrees: i32) -> media_status_t --- + + /** + * 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. + * + * Available since API level 21. + */ + AMediaMuxer_addTrack :: proc(muxer: ^AMediaMuxer, format: ^AMediaFormat) -> int --- + + /** + * Start the muxer. Should be called after AMediaMuxer_addTrack and + * before AMediaMuxer_writeSampleData. + * + * Available since API level 21. + */ + AMediaMuxer_start :: proc(muxer: ^AMediaMuxer) -> media_status_t --- + + /** + * Stops the muxer. + * Once the muxer stops, it can not be restarted. + * + * Available since API level 21. + */ + AMediaMuxer_stop :: proc(muxer: ^AMediaMuxer) -> media_status_t --- + + /** + * 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.) + * + * Available since API level 21. + */ + AMediaMuxer_writeSampleData :: proc(muxer: ^AMediaMuxer, trackIdx: uint, data: [^]u8, info: ^AMediaCodecBufferInfo) -> media_status_t --- + + /** + * Creates a new media muxer for appending data to an existing MPEG4 file. + * This is a synchronous API call and could take a while to return if the existing file is large. + * Only works for MPEG4 files matching one of the following characteristics: + * + * @param fd Must be opened with read and write permission. Does not take ownership of + * this fd i.e., caller is responsible for closing fd. + * @param mode Specifies how data will be appended the AppendMode enum describes + * the possible methods for appending.. + * @return Pointer to AMediaMuxer if the file(fd) has tracks already, otherwise, nullptr. + * {@link AMediaMuxer_delete} should be used to free the returned pointer. + * + * Available since API level 31. + */ + AMediaMuxer_append :: proc(fd: i32, mode: AppendMode) -> ^AMediaMuxer --- + + /** + * Returns the number of tracks added in the file passed to {@link AMediaMuxer_new} or + * the number of existing tracks in the file passed to {@link AMediaMuxer_append}. + * Should be called in INITIALIZED or STARTED state, otherwise returns -1. + * + * Available since API level 31. + */ + AMediaMuxer_getTrackCount :: proc(muxer: ^AMediaMuxer) -> int --- + + /** + * Returns AMediaFormat of the added track with index idx in the file passed to + * {@link AMediaMuxer_new} or the AMediaFormat of the existing track with index idx + * in the file passed to {@link AMediaMuxer_append}. + * Should be called in INITIALIZED or STARTED state, otherwise returns nullptr. + * {@link AMediaFormat_delete} should be used to free the returned pointer. + * + * Available since API level 31. + */ + AMediaMuxer_getTrackFormat :: proc(muxer: ^AMediaMuxer, idx: uint) -> ^AMediaFormat --- +} diff --git a/sensor.odin b/sensor.odin index a88898e..d5c4286 100644 --- a/sensor.odin +++ b/sensor.odin @@ -48,6 +48,11 @@ SensorType :: enum i32 { * field in the X, Y and Z axis. */ MAGNETIC_FIELD = 2, + + /* Deprecated in API level 15 + * This isn't defined in the NDK but the procedures report it as a valid sensor and can work with it. + */ + ORIENTATION = 3, /** * {@link ASENSOR_TYPE_GYROSCOPE} * reporting-mode: continuous @@ -69,6 +74,11 @@ SensorType :: enum i32 { * The pressure sensor value is returned in hPa (millibar). */ PRESSURE = 6, + + /* Deprecated in API level 15. Use AMBIENT_TEMPERATURE instead. + * This isn't defined in the NDK but the procedures report it as a valid sensor and can work with it. + */ + TEMPERATURE = 7, /** * {@link ASENSOR_TYPE_PROXIMITY} * reporting-mode: on-change @@ -381,8 +391,6 @@ ASensorVector :: struct { reserved: [3]u8, } -// TODO: sensor might be SensorType here, will need some code to confirm though. -// Not sure what "what" is, maybe code will confirm this too. AMetaDataEvent :: struct { what: i32, sensor: i32,