anodecs 0.1.6

Rust bindings to MediaCodec, with an easy-to-use API (formerly mediacodec)
docs.rs failed to build anodecs-0.1.6
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

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 (fork of mediacodec with anodecs name for crates.io).

Features Currently Implemented

  • MediaCodec
  • MediaExtractor
  • MediaMuxer
  • MediaFormat
  • Safe codec buffers abstraction
  • Some extra utilities to make working with the library easier

Feature flags

  • api24 — no additional APIs
  • api26createInputSurface, createPersistentInputSurface, setInputSurface, setParameters, signalEndOfInputStream
  • api28getBufferFormat, getName, setAsyncNotifyCallback, releaseCrypto, getInputFormat, AMediaCodecActionCode_isRecoverable, AMediaCodecActionCode_isTransient, getDouble/setDouble/getRect/setSize/setRect on MediaFormat
  • api29clear/copy on MediaFormat

Using

anodecs = "0.1"

Decoding example

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.