which codecs are supported for audio in android? G711 is supported. But is there any other like G729,...etc?
Take a look here:
http://developer.android.com/guide/appendix/media-formats.html
Im not sure if G.729 is explicitly available. But it might be used as a module in one of the other codecs that are listed on the page above.
HTH,
Sriram.
Take a look at: http://developer.android.com/reference/android/media/MediaCodecInfo.html
Have a piece of code which tell's all the avaible codecs (audio and video) in the device.
private List<String> mSupportedCodecs;
private void getSupportedCodecs() {
int numCodecs = MediaCodecList.getCodecCount();
mSupportedCodecs = new ArrayList<String>(numCodecs);
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
mSupportedCodecs.add(codecInfo.getName());
}
}
Related
public void getCodecInfo() {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(types[j]);
Log.d("CodecCapabilities", new Gson().toJson(capabilities));
//MediaCodecInfo.VideoCapabilities videoCapabilities = capabilities.getVideoCapabilities();
//Log.d("videoCapabilities", new Gson().toJson(videoCapabilities));
}
}
}
The above gave me this, what does the following number for profile and level tell me anything related to the video capabilities?
{"colorFormats":[21,2130708361],"profileLevels":[{"level":2048,"profile":1},{"level":2048,"profile":2},{"level":2048,"profile":8}],"flags":0}
If I uncomment these two lines in the above code, it crashes with this error message:
java.lang.NoSuchMethodError: android.media.MediaCodecInfo$CodecCapabilities.getVideoCapabilities
How can I query the android device, to find out the video capabilities? I'd like to know the max video bitrate and video resolution the device is capable to handle.
I guess that you are testing your code on a device running API < 21? If is the case, the getVideoCapabilies method is available only on devices running Android >= 21
Anyway, to get bitrate and supported width & height Ranges (API >=21 too...Humm may be related to getVideoCapabilies availability... I don't know :) ), you can use :
Range<Integer> bitrateRange = videoCapabilities.getBitrateRange();
Range<Integer> heightRange = videoCapabilities.getSupportedHeights();
Range<Integer> widthRange = videoCapabilities.getSupportedWidths();
You can take a look at this gist that I published a few days ago to get all capabilities for a given codec (Colors, profiles & levels are printed by names instead of numbers, which could be very helpful): TestMediaCodecInfoAsyncTask.java
I'm using the selectColorFormat method from bigflake to get supported input color format of encoder of MediaCodec.It works well on some tested devices except Huawei Mate7. The returned color format is COLOR_FormatYUV420Planar.So I configure it as the input format.But when encoding I found the input buffer's capacity is not correct,which should be 3*width*height/2.But it's smaller than that.So when queueInputBuffer called error occured. Then I observed the capabilities.colorFormats list, it has more than ten color formats.But on the normal devices the list has about 2 or 3 color formats.Then I chose the color format to COLOR_FormatYUV420SemiPlanar and it works well on Mate7 too.
So I doubt whether this is a bug of Mate7 version or the bug of selectColorFormat method?
And I find the anwser of FAQ Q5 has :
#20 COLOR_FormatYUV420PackedPlanar (also I420)
#39 COLOR_FormatYUV420PackedSemiPlanar (also NV12)
#0x7f000100 COLOR_TI_FormatYUV420PackedSemiPlanar (also also NV12)
What's the meaning of also I420 and also NV12?Does it mean the layout is all the same with I420 or NV12?Because I have tested I420 and NV12, but haven't come across these three colors device.
The selectColorFormat method is as belows:
private MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
return codecInfo;
}
}
}
return null;
}
private int selectColorFormat(String mimeType) {
MediaCodecInfo codecInfo = selectCodec(mimeType);
int colorFormat = 0;
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
for (int i = 0; i < capabilities.colorFormats.length; i++) {
if (isRecognizedFormat(capabilities.colorFormats[i])) {
colorFormat = capabilities.colorFormats[i];
break;
}
}
return colorFormat;
}
private boolean isRecognizedFormat(int colorFormat) {
switch (colorFormat) {
// these are the formats we know how to handle for this test
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
return true;
default:
return false;
}
}
All devices running Android 4.3 (API 18) or later support YUV input in I420 or NV12 formats. I can say this with confidence because they are part of the CTS tests that all "official" Android devices must pass.
The color constants returned by the codecs have multiple values that map to either I420 or NV12. You can see in the bigflake sample code how this is handled (e.g. generateFrame() in EncodeDecodeTest).
The input buffer capacity should be equal to or slightly larger than width * height * 3 / 2. If you are encountering buffer overrun exceptions, make sure you are clearing the buffer before copying data into it.
I've compiled an FFMPEG library for use on Android with libx264 and using the NDK.
I want to encode an MPEG video file however the application is failing when opening the encoder codec, in avcodec_open2.
The FFMPEG logs I receive from avcodec_open2 are below with the function returning -22.
Picture size %ux%u is invalid.
ignoring invalid width/height values
Specified pix_fmt is not supported
On windows this code works fine, it's only on Android that there is a failure. Any ides why this would fail on Android?
if (!(codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO)))
{
return -1;
}
//Allocate context based on codec
if (!(context = avcodec_alloc_context3(codec)))
{
return -2;
}
//Setup Context
// put sample parameters
context->bit_rate = 4000000;
// resolution must be a multiple of two
context->width = 1280;
context->height = 720;
// frames per second
context->time_base = (AVRational){1,25};
context->inter_quant_bias = 96;
context->gop_size = 10;
context->max_b_frames = 1;
//IDs
context->pix_fmt = AV_PIX_FMT_YUV420P;
context->codec_id = AV_CODEC_ID_MPEG1VIDEO;
context->codec_type = AVMEDIA_TYPE_VIDEO;
if (AV_CODEC_ID_MPEG1VIDEO == AV_CODEC_ID_H264)
{
av_opt_set(context->priv_data, "preset", "slow", 0);
}
if ((result = avcodec_open2(context, codec, NULL)) < 0)
{
//Failed opening Codec!
}
This problem was caused by building FFMPEG with outdated source code.
I got the most recent source from https://www.ffmpeg.org/ and compiled it in the same way and the new library works fine.
Note: I hadn't considered the full implications regarding licenses of using libx264. I've since dropped it.
For my application i created video from set of images by using javacv/opencv in android.but that video plays with out sound.so i want to add my recorded audio(mp3 file) to that generated video how can i achieve it?
This is my code which is used to get video from images,
String path =SCREENSHOT_FOLDER2;
File folder = new File(path);
listOfFiles = folder.listFiles();
if(listOfFiles.length>0)
{
iplimage = new opencv_core.IplImage[listOfFiles.length];
for (int j = 0; j < listOfFiles.length; j++) {
String files="";
if (listOfFiles[j].isFile())
{
files = listOfFiles[j].getName();
}
String[] tokens = files.split("\\.(?=[^\\.]+$)");
String name=tokens[0];
System.out.println(" j " + name);
iplimage[j]=cvLoadImage("/mnt/sdcard/images/"+name+".png");
}
}
File videopath = new File(SCREENSHOT_FOLDER3);
videopath.mkdirs();
FFmpegFrameRecord recorder = new
FFmpegFrameRecord(SCREENSHOT_FOLDER3+
"video"+System.currentTimeMillis()+".mp4",320,480);
try {
recorder.setCodecID(CODEC_ID_MPEG4); //CODEC_ID_MPEG4
//CODEC_ID_MPEG1VIDEO
recorder.setBitrate(sampleVideoBitRate);
recorder.setFrameRate(10);
recorder.setPixelFormat(PIX_FMT_YUV420P); //PIX_FMT_YUV420P
recorder.start();
int x = 0;
int y = 0;
for (int i=0;i< 300 && x<iplimage.length;i++)
{
recorder.record(image[x]);
if (i>(y+10)) {
y=y+1;
x++;
}
}
recorder.stop();
}
catch (Exception e){
e.printStackTrace();
}
now how to integrate audio file(.mp3) file in this code.
OpenCV, and subsequently JavaCV has no support for audio.
You have to go with a different library for it. Look at the Android support for video/audio, third-pary libs, or any other way you may find useful.
But don't just expect OpenCV to help you because it's support for audio is 0%.
I would not say that JavaCV has no support for audio, as it integrates a lot of libraries that opencv does not - ffmpeg for example. Check this long thread for that issue.
Is there a way to ask an Android device what audio and video Codecs it supports for encoding?
I found devices that do not support some of the codecs listed as mandatory in
http://developer.android.com/guide/appendix/media-formats.html
and there seem to be devices supporting additional codec not listed there.
That could be interesting for you:
private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
return codecInfo;
}
}
}
return null;
}
Found it here. AS you can see you get the number of installed codecs with MediaCodecList.getCodecCount();. With MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); you get information about a specific codec out of the list. codecInfo.getName() for example tells you title/name of the codec.
Is there a way to ask an Android device what audio and video Codecs it supports for encoding?
I really wish there were, but there is not, at least through ICS.
Jelly Bean offers a MediaCodec class. While it does not have a "give me a list of supported codecs", it does have createEncoderByType(), where you pass in a MIME type. Presumably, that will throw a RuntimeException or return null if your desired MIME type is not supported. And I cannot promise that just because MediaCodec reports that an encoder is available that it is guaranteed to work from, say, MediaRecorder.
The simplest way is using
MediaCodecList(MediaCodecList.ALL_CODECS).codecInfos
It returns a array of all encoders and decoders available on your devices like this image.
And then, you can use filter to query the specific encoders and decoders you are looking for. For example:
MediaCodecList(MediaCodecList.ALL_CODECS).codecInfos.filter {
it.isEncoder && it.supportedTypes[0].startsWith("video")
}
This returns all available video encoders.
Here is an updated code based on Jonson's answer, written in Kotlin and not using deprecated methods:
fun getCodecForMimeType(mimeType: String): MediaCodecInfo? {
val mediaCodecList = MediaCodecList(MediaCodecList.REGULAR_CODECS)
val codecInfos = mediaCodecList.codecInfos
for (i in codecInfos.indices) {
val codecInfo = codecInfos[i]
if (!codecInfo.isEncoder) {
continue
}
val types = codecInfo.supportedTypes
for (j in types.indices) {
if (types[j].equals(mimeType, ignoreCase = true)) {
return codecInfo
}
}
}
return null
}