I want to decode and display h264 frame over my screen. Now all I wanted to do is to use omx codec to decode my frames as it decodes in hardware which helps achieve fps for high resolutions. Till now all I come to know is there are different way to access hardware decoder. I come across some names like stagefright, omxcodec, openmax. All are these are different things. I want to decode frame by frame. and upto my knowledge android libraries accept only file path or url of media. But here my requirement is different. I need to decode frame by frame. So can someone tell me where can I start digging? I come to know that in latest version of android, they have published api to decode. But I want to support all version of android. So any suggestion or guidance will be great.
Thanks.
You are right, indeed at the top level libstagefright library has a "stream" interface.
That is, you create audio- or video-source, configure codecs, and then start the process of encoding or decoding.
However, using an interface OMXCodec you can obtain access to the individual frames.
Unfortunately, I do not know any source of official OMXCodec documentations.
The only source - these are examples of the code in the Android repository.
If you want to know more about how to use OMXCodec, you can view the AwesomePlayer.cpp file
(http://gitorious.org/rowboat/frameworks-base/blobs/rowboat-ics/media/libstagefright/AwesomePlayer.cpp)
Using the library libstagefright is clear from the StagefrightRecorder.cpp (in the same repository)
Also useful information about the OMXCodec architecture is
here
P.S. Remember that the OMXCodec API not stable and may vary from version to version...
Related
I am using Qt 5.9 based app which runs on embedded linux & android. The application processes real time data using OpenGL ES 3.0 & displays OpenGL textures at real time. I am displaying at the rate of 30+ frames per second which makes it pretty much real time & appears like a video.
I need to save an mp4 from a 30 to 40 frames that are displayed using OpenGL textures. As I understand, I can leverage Qt Multimedia to do this. But I lack the knowledge of how to do this. I am trying read & understand the how part from links like here & here.
One the mp4 is saved, playback can be done using QMediaPlayer as explained here. That looks darn simple. But I am struggling to figure how get my OpenGL textures saved into a .mp4 when I need them to.
So, How do I save a .mp4 video out of the OpenGL textures that are displayed on a QML item?
Pointing out to any basic example that exists would also help.
I don't think Qt will do you any favors when it comes to content creation, Qt's multimedia facilities are purely for content consumption purposes. You can play MM, not make MM.
You will have you explicitly use one of the many available MM libraries out there - vlc, ffmpeg, gstreamer, libav to name a few.
I have a remuxing.c example working from ffmpeg but I need to change resolution to minimize file size, anybody can explain me how to do that? Or if there is another way to "compress" mp4 files without command line? I'm a begginer with FFmpeg and need to send video files from android to server, and I'm deploying a NDK library to make this job because FFmpeg command-line implementation have some limitations and is very slow.
Thanks
You should take a look at the filtering video and the transcoding examples. The first one goes through how you add "filters" in ffmpeg. It includes a scaling filter, which will rescale the video to a given resolution. Transcoding includes some filtering, and you can actually change the filter_spec string to be whatever you want, and the program should scale your input video.
This is probably not the best solution, I just found it myself, but it at least introduces you to the components being used.
I am trying to create a video from series of images in android.
I have come across these three options MediaCodec, ffmpeg using ndk and jcodec. Can someone let me know which one of them is best and easiest. I didn't find any proper documentation so can somebody please post their working example?
If you are talking about API 4.3+ in general you need to get input surface from encoder, copy image to the texture that comes along with the surface, put correct timestamp and send it back to encoder. and do it
fps (frames per second) * resulted video duration in seconds
times. encoder bitstream after encoder should go to the muxer, so finally you will get mp4 file.
It requires rather much coding:)
I suggest you to try free Intel Media Pack: https://software.intel.com/en-us/articles/intel-inde-media-pack-for-android-tutorials
It has a sample - JpegSubstituteEffect, it allows to create videos from images. The idea is to take a dummy video (black video and quiet audio) and to substitute all black frame by coping images. It could be easily enhanced to creating a video from series of images. I know a couple of applications in Google Play making the same using Media Pack
I tried JCodec 1.7 for Android. This is very simple compared to the other two options and works. There is class SequenceEncoder in the android package that accepts Bitmap instances and encodes them in to video. I ended up cloning this class into my app to override some of the settings e.g. fps. Problem with JCodec is that performance is dismal - encoding single 720x480 pixels frame takes just about 45 seconds. I wanted to do timelapse videos possibly at fullHD and was initially thinking any encoder will do as I was not expecting encoding a frame to take more than a second (minimal interval between frames in my app is 3 seconds). As you can guess with 45 seconds per frame JCodec is not a fit.
I am monitoring your question for other answers that may be helpful.
The MediaCodec/MediaMuxer way seems ok but it is insanely complex. I need to learn quite a bit about OpenGL ES, video formats and some Android voodoo to get this going. Ohh and this only works on the latest crop of phones 4.3+. This is real shame for Google with all of their claims to fame. I found some Stackoverflow discussions on the topic. Two sub-paths exist - the OpenGL way is device independent. There is another way which involves transcoding your RGB Bitmap data to YUV. the catch with YUV is that there are 3 flavours of it depending on the device HW - planar, semi planar and semi planar compressed (I am not sure if a 4th way is not coming in the future so...).
Here are couple useful links on the OpenGL way
CTS test - https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
Many CTS like tests - http://bigflake.com/mediacodec/#EncodeDecodeTest
Two of them seem to be relevant and useful
EncodeAndMuxTest - http://bigflake.com/mediacodec/EncodeAndMuxTest.java.txt
CameraToMpegTest - http://bigflake.com/mediacodec/CameraToMpegTest.java.txt (I believe this to be closest to what I need, just need to understand all the OpenGL voodoo and get my Bitmap in as texture filling up the entire frame i.e. projections, cameras and what not comes into play)
ffmpeg route does not seem direct enough too. Something in C++ accepting stuff from Java...I guess some weird conversions of the Bitmap to byte[]/ByteBuffer will be first needed - cpu intensive and slow. I actually have JPEG byte[] but am not sure this will come handy to the ffmpeg library. I am not sure if ffmpeg is taking leverage of the GPU or other HW acceleration so it may well end up at 10 seconds per frame and literally baking the phone.
FFmpeg can implement this task. You first need compile ffmpeg library in Android (refer to this article "How to use Vitamio with your own FFmpeg build")
You could refer the samples in FFmpeg to figure out how to implement your task.
In Android implement your task in C++; then use JNI to integrate the C++ code into your Android app.
I take camera preview frames from android camera in 640x480 (sufficient to me) and do some modifications over them. But now I need to encode those to new MP4 file (with audio).
Is this some how possible? I can't use ffmpeg due to its not so good license, but I've found Stagefright framework which should be probably capable of doing that. But I did not find any sort of official documentation or tutorials to do such a thing I need to do.
Is there a way to do it with this framework please? I don't need codes, I would be very glad just for pointing me the right direction.
There is one scenario where the use-case described is realized. Consider a scenario where the Camera output is fed to an OpenGL library where some effects are applied on the preview frames which need to be recorded.
Well in this case, you can use the traditional MediaRecorder with GrallocSource instead of CameraSource. The setup would look like thus:
MediaRecorder is set up with the GrallocSource. The input surfaces for recording are provided by the Camera + OpenGL combined operation which implement a SurfaceTextureClient. A good example for this can be found in SurfaceMediaSource_test modules.
stagefright is quite good if you must support API 9 and higher. But this framework is not official, as you saw. You can use the sample code in platform/frameworks/av at your risk.
The google source includes CameraSource, which provides the camera frames directly to the encoder. While this approach may be much more efficient (the pixels are not copied to the user space at all), it does not allow manipulation. It is possible to modify the C++ source, but I strongly recommend to access the Camera in Java, and pass the preview frames via JNI to stagefrght (OpenMAX) encoder. On some devices, this may force you to use software encoder. You must convert the video frames to YUV planar format for the encoder. See libyuv for optimized converters.
If you can restrict your support to API 16 and higher, it is safer to use the official Java MediaCdec API.
I want to create live painting video as export feature for a painting application.
I can create a video with a series of images, with the use of a library ( FFMPEG or MediaCodec). But, this would require too much processing power to compare the images and encode the video.
While drawing, I know exactly which pixels are changed. So, I can save lot of processing if I can pass this info to FFMPEG, instead of having the FFMPEG figure this out from the images.
Is there away to efficiently encode the video for this purpose ?
It should not require "too much processing power" for MediaCodec. Because, for example, device is capable to write video in real time, some of them write full HD video.There's another thing : each MediaCodec's encoder requires pixel data in specific format, you should query API for supported capabilities before using the API. Also it will be tricky to make your app work on all devices with MediaCodec if your app produces only one pixel format, because probably not all of devices will support it(another words: different vendors have different MediaCodec implementation).