Android native codec interfaces MediaCodec - The stepped pit

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https: //blog.csdn.net/gb702250823/article/details/81669684
want us to respect everyone's achievements, reproduced, please indicate the source:
https://blog.csdn.net/gb702250823/article/details/81669684
This article comes from the pot of small blog

Keyframe
MediaCodec There are two ways to trigger the output key frame, KEY_FRAME_RATE KEY_I_FRAME_INTERVAL and one parameter set by the configuration of automatic triggering, and second, during operation triggered by an output key frame setParameters manually.

Automatically trigger output key frame
set I (key frame) time interval MediaCodec hard coded, the api is so provided

mediaFormat.setInteger (MediaFormat.KEY_I_FRAME_INTERVAL, 1); // key frame interval units S
. 1
to automatically trigger the actual number of frames is triggered, for example, set the frame rate to 20 FPS, the key frame interval is 1s, that will be 20 frames per outputting a key frame, the frame rate is lower than the actual configuration once the frame rate, it will lead to the key frame interval time becomes long. Since MediaCodec start after the frame rate can not change the configuration / key frame interval, so if you want to change the key frame interval number of frames, it is necessary to restart the encoder.

Manually trigger output keyframe:

if - after (System.currentTimeMillis () timeStamp> = 1000 ) {// 1000 ms, the parameter set
timeStamp = System.currentTimeMillis ();
IF (Build.VERSION.SDK_INT> = 23 is) {
the Bundle the Bundle the params = new new ();
params.putInt (MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
mMediaCodec.setParameters (params);
}
}

keyframe stepped pit
sometimes you will find the key frame mode automatically trigger fails

By investigation found the real reason is that the video input source, if it is re-fed to acquire video data is not MediaCodec way to control the number of key frames output by way of PreviewCallback the Camera.
It found that when the color format is chosen to support yuv420p encoder, KEY_I_FRAME_INTERVAL set invalid;
select encoder yuv420sp the support, KEY_I_FRAME_INTERVAL the valid;

Want to control the number of output keys must obtain input Surface by calling MediaCodec.createInputSurface () method, and then the real key to control the number of frames rendered by the Opengl fed MediaCodec to.

// determines whether the output data is the key frame method:
! = Boolean KeyFrame (bufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) = 0;

some models MediaCodec.configure directly crash
coding is not provided in some configurations mandatory throws IllegalStateException
see the examples stackoverflow

If the default initialization MediaFormat wide video stream high above the current phone supports a maximum resolution of decoding it will crash when you call the MediaCodec.configure. The width and height of a little time to set up small MediaFormat.createVideoFormat ok, then there will be another problem is that if I set the 1080 * 720 video stream to a 1920 * 1080 will not be affected? If the current maximum resolution of the device is higher than this value, even if the default value is not the same, still picture can be decoded correctly and 1920 * 1080 display. So if below this value it? In both cases the value of green screen /MediaCodec.dequeueInputBuffer been throwing IllegalStateException

How to get the current device supports a maximum resolution of decoding
have such a file for each phone, / system / etc / media_codecs.xml ( your path). This is an xml file, you can see directly support various video formats circumstances under MediaCodecs-> Decoders nodes, Huawei glory 7x Android 8.0 Case Study


Get the width and height of the decoded video

//获得音视频的配置器MediaFormat
private static MediaFormat getFormat(String path,boolean isVideo) {
try {
MediaExtractor mediaExtractor = new MediaExtractor();
mediaExtractor.setDataSource(path);
int trackCount = mediaExtractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
if (trackFormat.getString(MediaFormat.KEY_MIME).startsWith(isVideo ? "video/" :"audio/")) {
return mediaExtractor.getTrackFormat(i);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//单独获取宽高
MediaFormat newFormat = getFormat(path,true);
videoWidth newFormat.getInteger = int (MediaFormat.KEY_WIDTH);
int = videoHeight newFormat.getInteger (MediaFormat.KEY_HEIGHT);
Get the width and height // when combined coding
MediaFormat mMediaCodec.getOutputFormat newFormat = ();
int = videoWidth newFormat.getInteger (MediaFormat. KEY_WIDTH);
int videoHeight = newFormat.getInteger (MediaFormat.KEY_HEIGHT);

some models MediaCodec.dequeueOutputBuffer been reported IllegalStateException
some models would have been stuck in MediaCodec.INFO_TRY_AGAIN_LATER, some also for this reason
that the maximum configuration model hardware decoding resolution rate lower than the current resolution of the video stream

A data output section models too short, or 0
After removing the output buffer, and to manually set the position limit (api19 or less must be set), the encoder device is not provided some two values, leading to impossible to extract data correctly; removed after the input buffer, to invoke manually clear. See bigflake FAQ # 11

mMediaCodec.createInputSurface () failed to create or remove undesirable data
while mMediaCodec.createInputSurface () has been introduced from the API 18, but used in some models API 18 will cause the output of the data encoder particularly small, the screen is black Therefore Surface input mode is enabled from the API 19.
After mMediaCodec.createInputSurface () must mediaformat.configure (..), called before mediacodec.start ().

BufferInfo is provided on presentationTimeUs
if not properly disposed presentationTimeUs, the encoder apparatus will lose some of the incoming frame, or the output image quality is poor, see the FAQ #. 8 bigflake;
MediaCodec using microseconds, milliseconds, and most satisfied using java second, properly handle unit

If the input surface, how you want to operate dropped frames
?? (when to start coding condition) meet the conditions after the start coding. This is a controllable do.

if (mBufferInfo.size = 0 && ?? (when to start encoding condition)!) {
outputBuffer.position (mBufferInfo.offset);
outputBuffer.limit (mBufferInfo.offset mBufferInfo.size +);
// mMuxer.writeSampleData (mTrackIndex, encodedData, bufferInfo);
} the else {
outputBuffer.clear ();
}
// end processing, release resources output buffer
mMediaCodec.releaseOutputBuffer (outputBufferIndex, false);

output data and write data to the MP4 in the same thread, otherwise it will sporadic Huaping, mosaics
following practices will Huaping, mosaic

IF (mBufferInfo.size = 0!) {
outputBuffer.position (mBufferInfo.offset);
outputBuffer.limit (mBufferInfo.offset mBufferInfo.size +);
// here lazy thread blocked waiting for the data written in the action, lazy. Know the situation is OK
new new the Thread (the Runnable new new () {
@Override
public void RUN () {
// mMuxer.writeSampleData (mTrackIndex, encodedData, bufferInfo);
}
}). Start ();
}

on bitrate_mode configuration issues
MediaCodec in the bitrate mode there is a pit, for example, I want to make sure CBR supports, then calls isBitrateModeSupported () before setting judgment, so there will be problems.

// MediaCodecInfo.java
public boolean isBitrateModeSupported(int mode) {
for (Feature feat: bitrates) {
if (mode == feat.mValue) {
return (mBitControl & (1 << mode)) != 0;
}
}
return false;
}

mode是否支持从bitrates判断

Private static Final the Feature [] bitrates of = new new the Feature [] {
new new the Feature ( "the VBR", BITRATE_MODE_VBR, to true),
new new the Feature ( "the CBR", BITRATE_MODE_CBR, to false),
new new the Feature ( "CQ", BITRATE_MODE_CQ, to false)
};

framework actually write it dead! Not from the hardware or xml, the xml is written and supported.
vendor / rockchip / common / vpu / etc / media_codecs.xml

If you write code more stringent, first with isBitrateModeSupported () to determine whether to support CBR, then on the tragedy.
In addition, by default, if not take the initiative to set up the upper bitrate_mode then returns VBR. About VBR is default to distinguish CBR VBR CQ, you can view the Android native codec interfaces MediaCodec - The flow control completely Resolution.

About level, profile settings
due to low quality of the display data after the video encoding, it is necessary to adjust the mass. This time required in this setting level, profile

Profile is to describe the characteristics of video compression (CABAC way, the number of color samples, etc.).
Level is a description of the characteristics of the video itself (bit rate, resolution, fps).
In simple terms, Profile higher, it shows the use of the more advanced compression characteristics.
The higher the Level, video bit rate, resolution, fps higher

// does not support setting Profile and Level, but should default settings
mediaFormat.setInteger (MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
mediaFormat.setInteger ( "Level", MediaCodecInfo.CodecProfileLevel.AVCLevel41); // Level 4.1

on setting these two parameters, I found that on some devices, set an invalid, or default by the investigation
because android7.0 or less, android died internal write parameters, coding it can only be Baseline, unless the system is changed this BUG , whether those settings are invalid, and even lead to failure configure parameters.
----------------
Disclaimer: This article is CSDN blogger "small the pot" in the original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source and this link statement.
Original link: https: //blog.csdn.net/gb702250823/article/details/81669684

Guess you like

Origin www.cnblogs.com/laughingQing/p/11611929.html
Recommended