anodecs 0.1.6

Rust bindings to MediaCodec, with an easy-to-use API (formerly mediacodec)
# anodecs (fork of rust_mediacodec)
This library provides Rust bindings to the Android MediaCodec APIs. It also adds some pretty nifty utilities to make working with buffers on Android easier.

Published as [`anodecs`](https://crates.io/crates/anodecs) (fork of `mediacodec` with `anodecs` name for crates.io).

## Features Currently Implemented
- [x] MediaCodec
- [x] MediaExtractor
- [x] MediaMuxer
- [x] MediaFormat
- [x] Safe codec buffers abstraction
- [x] Some extra utilities to make working with the library easier

## Feature flags

- `api24` — no additional APIs
- `api26``createInputSurface`, `createPersistentInputSurface`, `setInputSurface`, `setParameters`, `signalEndOfInputStream`
- `api28``getBufferFormat`, `getName`, `setAsyncNotifyCallback`, `releaseCrypto`, `getInputFormat`, `AMediaCodecActionCode_isRecoverable`, `AMediaCodecActionCode_isTransient`, `getDouble`/`setDouble`/`getRect`/`setSize`/`setRect` on `MediaFormat`
- `api29``clear`/`copy` on `MediaFormat`

## Using

```toml
anodecs = "0.1"
```

## Decoding example

```rust
use log::debug;
use anodecs::{DequeueInputError, DequeueOutputError, Frame, MediaCodec, MediaExtractor, SampleFormat, VideoFrame};

#[unsafe(no_mangle)]
extern "C" fn process() {
    let mut extractor = MediaExtractor::from_url("/path/to/a/resource").unwrap();

    debug!("Track count: {}", extractor.track_count());

    let mut decoders = vec![];

    for i in 0..extractor.track_count() {
        let format = extractor.track_format(i).unwrap();
        debug!("{}", format.to_string());
        let mime_type = format.get_string("mime").unwrap();
        let mut codec = MediaCodec::create_decoder(&mime_type).unwrap();

        codec.init(&format, None, 0).unwrap();
        codec.start().unwrap();
        decoders.push(codec);
        extractor.select_track(i).unwrap();
    }

    while extractor.has_next() {
        let index = extractor.track_index();
        if index < 0 {
            break;
        }

        let codec = &mut decoders[index as usize];

        loop {
            match codec.dequeue_input(100) {
                Ok(mut buffer) => {
                    match extractor.read_next(&mut buffer) {
                        Ok(true) => {}
                        Ok(false) => {
                            buffer.cancel();
                            break;
                        }
                        Err(_) => {
                            buffer.cancel();
                            break;
                        }
                    }
                }
                Err(DequeueInputError::TryAgainLater) => break,
                Err(DequeueInputError::CodecError(e)) => {
                    debug!("Codec error: {e:?}");
                    break;
                }
            }

            // When the buffer gets dropped (here), the buffer will be queued back to MediaCodec
            // And we don't have to do anything else
        }

        loop {
            match codec.dequeue_output(100) {
                Ok(mut buffer) => {
                    if let Some(ref frame) = buffer.frame() {
                        match frame {
                            Frame::Audio(value) => match value.format() {
                                SampleFormat::S16(_) => {}
                                SampleFormat::F32(_) => {}
                            },
                            Frame::Video(value) => match value {
                                VideoFrame::Hardware => {}
                                VideoFrame::RawFrame(_) => {}
                            },
                        }
                    }
                    buffer.set_render(true);
                }
                Err(DequeueOutputError::TryAgainLater) => break,
                Err(DequeueOutputError::OutputFormatChanged) => {
                    debug!("Output format changed");
                    continue;
                }
                Err(DequeueOutputError::OutputBuffersChanged) => continue,
                Err(DequeueOutputError::CodecError(e)) => {
                    debug!("Codec error: {e:?}");
                    break;
                }
            }
        }
    }
}
```

You can find more examples in the **examples** directory.