GithubHelp home page GithubHelp logo

octaplexsys / litr Goto Github PK

View Code? Open in Web Editor NEW

This project forked from linkedin/litr

0.0 1.0 0.0 350 KB

Lightweight hardware accelerated video/audio transcoder for Android.

License: BSD 2-Clause "Simplified" License

Java 100.00%

litr's Introduction

LiTr

LiTr (pronounced "lai-tr") is a lightweight video/audio transformation tool which supports transcoding video and audio tracks with optional frame modification.

In its current iteration LiTr supports:

  • changing resolution and/or bitrate of a video track(s)
  • changing bitrate of an audio track(s)
  • overlaying bitmap watermark onto video track(s)
  • including/excluding tracks, which allows muxing/demuxing tracks
  • transforming tracks individually (e.g. apply overlay to one video track, but not the other)

By default, LiTr uses Android MediaCodec stack for hardware accelerated decoding/encoding and OpenGL for rendering. It also uses MediaExtractor and MediaMuxer to read/write media.

Getting Started

Simply grab via Gradle:

 implementation 'com.linkedin.android.litr:litr:1.3.2'

...or Maven:

<dependency>
  <groupId>com.linkedin.android.litr</groupId>
  <artifactId>litr</artifactId>
  <version>1.3.2</version>
</dependency>

How to Transform a Video

First, instantiate MediaTransformer with a Context that can access Uris you will be using for input and output. Most commonly, that will be an application context.

MediaTransformer mediaTransformer = new MediaTransformer(getApplicationContext());

Then simply call transform method to transform your video:

mediaTransformer.transform(requestId,
                           sourceVideoUri,
                           targetVideoFilePath,
                           targetVideoFormat,
                           targetAudioFormat,
                           videoTransformationListener,
                           MediaTransformer.GRANULARITY_DEFAULT,
                           glFilters);

Few notable things related to transformation:

  • make sure to provide a unique requestId, it will be used when calling back on a listener, or needed when cancelling an ongoing transformation
  • target formats will be applied to all tracks of that type, non video or audio tracks will be copied "as is"
  • passing null target format means that you don't want to modify track(s) of that type
  • transformation is performed asynchronously, listener will be called with any transformation progress or state changes
  • by default listener callbacks happen on a UI thread, it is safe to update UI in listener implementation. It is also possible to have them on a non-UI transformation thread, for example, if any "heavy" works needs to be done in listener implementation.
  • if you want to modify video frames, pass in a list of GlFilters, which will be applied in order
  • client can call transform multiple times, to queue transformation requests
  • video will be written into MP4 container, we recommend using H.264 ("video/avc" MIME type) for target encoding
  • progress update granularity is 100 by default, to match percentage

Ongoing transformation can be cancelled by calling cancel with its requestId:

mediaTransformer.cancel(requestId);

When you no longer need MediaTransformer, please release it. Note that MediaTransformer instance becomes unusable after you release it, you will have to instantiate a new one.

mediaTransformer.release();

Handling errors

When transformation fails, exception is not thrown, but rather provided in TransformationListener.onError callback. LiTr defines its own exceptions for different scenarios. For API >= 23, LiTr exception will also contain MediaCodec.CodecException as a cause.

Reporting statistics

When possible, transformation statistics will be provided in listener callbacks. Statistics include source and target track formats, codecs used and transformation result and time for each track.

Beyond Defaults

By default, LiTr uses Android MediaCodec stack to do all media work, and OpenGl for rendering. But this is not set in stone.

At high level, LiTr breaks down transformation into five essential steps:

  • reading encoded frame from source container
  • decoding source frame
  • rendering a source frame onto target frame, optionally modifying it (for example, overlaying a bitmap)
  • encoding target frame
  • writing encoded target frame into target container

Each transformation step is performed by a component. Each component is abstracted as an interface:

  • MediaSource
  • Decoder
  • Renderer
  • Encoder
  • MediaTarget

This allows clients pass in their own implementations of different transformation steps using more "low level" transform API:

transform(requestId,
          mediaSource,
          decoder,
          videoRenderer,
          encoder,
          mediaTarget,
          targetVideoFormat,
          targetAudioFormat,
          listener,
          granularity)

When using your own component implementations, make sure that output of a component matches the expected input of a next component. For example, if you are using a custom Encoder (AV1?), make sure it accepts whatever frame format Renderer produces (GlSurface, ByteBuffer) and outputs what MediaTarget expects as an input.

Another way to gain even finer control over transformation is to use "track transformation" API:

tranform(requestId,
         List<TrackTransform> trackTransforms,
         listener,
         granularity)

This API allows defining components and parameters per media track, thus allowing track based operations, such as muxing/demuxing tracks, transcoding different tracks differently, changing track order, etc.

Using Filters

You can use custom filters to modify video frames. Write your own in OpenGL as an implementation of GlFilter interface when you need to make extra draw operations which do not need access to source video frames. If you need to change how source video frame is rendered onto a target video frame, implement GlFrameRender interface. There are several filters already available from "filter pack" library, which is available via Gradle:

 implementation 'com.linkedin.android.litr:litr-filters:1.3.2'

...or Maven:

<dependency>
  <groupId>com.linkedin.android.litr</groupId>
  <artifactId>litr-filters</artifactId>
  <version>1.3.2</version>
</dependency>

You can pass in a list of filters when transforming a video. Keep in mind that filters will be applied in the order they are in the list, so ordering matters.

Using in Tests

MediaTransformer is very intentionally not a singleton, to allow easy mocking of it in unit tests. There is also MockMediaTransformer for UI tests, which can synchronously "play back" a sequence of listener callbacks.

Testing

Core business logic in LiTr is well covered by unit tests. LiTr is designed to use dependency injection pattern, which makes it very easy to write JVM tests with mocked dependencies. We use Mockito framework for mocking.

Demo App

LiTr comes with pretty useful demo app, which lets you transcode video/audio tracks with different parameters, in addition to providing sample code.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

For the versions available, see the tags on this repository.

Authors

  • Izzat Bahadirov - Initial work - LiTr

See also the list of contributors who participated in this project.

License

This project is licensed under the BSD 2-Clause License - see the LICENSE file for details

Acknowledgments

  • A huge thank you to ypresto for his pioneering work on android-transcoder project, which was an inspiration and heavy influence on LiTr
  • A thank you to Google's AOSP CTS team for writing Surface to Surface rendering implementation in OpenGL, which became a foundation for GlRenderer in LiTr
  • A shout out to my awesome colleagues Amita Sahasrabudhe, Long Peng and Keerthi Korrapati for contributions and code reviews
  • A shout out to our designer Mauroof Ahmed for giving LiTr a visual identity
  • A shout out to PurpleBooth for very useful README.md template

litr's People

Contributors

izzytwosheds avatar tguerin avatar cerisier avatar lu16j avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.