欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

android无法解码avcmp4,android - Android中的MediaCodec编码的H.264 avc视频无法播放 - 堆栈内存溢出...

发布时间:2023/12/14 36 豆豆
生活随笔 收集整理的这篇文章主要介绍了 android无法解码avcmp4,android - Android中的MediaCodec编码的H.264 avc视频无法播放 - 堆栈内存溢出... 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

背景:

我一直在努力实现像录像机这样的Vine两天。 首先,我尝试了MediaRecorder。 但我需要的视频可能是由小视频片段组成的。 此类不能用于录制短时视频剪辑。 然后我找到了MediaCodec,FFmpeg和JavaCV。 FFmpeg和JavaCV可以解决这个问题。 但我必须使用许多库文件编译我的项目。 它会生成一个非常大的APK文件。 所以我更喜欢通过MediaCodec实现它,尽管这个类只能在Android 4.1之后使用。 90%的用户会满意。

结果:

我终于得到了编码文件,但无法播放。 我通过FFprobe检查了信息,结果如下:

输入#0,h264,来自'test.mp4':持续时间:N / A,比特率:N / A流#0:0:视频:h264(基线),yuv420p,640x480,25 fps,25 tbr,1200k tbn, 50 tbc

我不太了解H.264编码的机制。

码:

从此链接修改

public class AvcEncoder {

private static String TAG = AvcEncoder.class.getSimpleName();

private MediaCodec mediaCodec;

private BufferedOutputStream outputStream;

private int mWidth, mHeight;

private byte[] mDestData;

public AvcEncoder(int w, int h) {

mWidth = w;

mHeight = h;

Log.d(TAG, "Thread Id: " + Thread.currentThread().getId());

File f = new File("/sdcard/videos/test.mp4");

try {

outputStream = new BufferedOutputStream(new FileOutputStream(f));

Log.i("AvcEncoder", "outputStream initialized");

} catch (Exception e) {

e.printStackTrace();

}

try {

mediaCodec = MediaCodec.createEncoderByType("video/avc");

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", w,

h);

mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);

mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);

// mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,

// MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);

mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,

MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);

mDestData = new byte[w * h

* ImageFormat.getBitsPerPixel(ImageFormat.YV12) / 8];

mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);

mediaCodec.configure(mediaFormat, null, null,

MediaCodec.CONFIGURE_FLAG_ENCODE);

mediaCodec.start();

}

public void close() {

try {

mediaCodec.stop();

mediaCodec.release();

mediaCodec = null;

// outputStream.flush();

outputStream.close();

} catch (IOException e) {

}

}

public void offerEncoder(byte[] input) {

try {

CameraUtils.transYV12toYUV420Planar(input, mDestData, mWidth,

mHeight);

ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();

ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();

int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);

if (inputBufferIndex >= 0) {

ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];

inputBuffer.clear();

inputBuffer.put(mDestData);

mediaCodec.queueInputBuffer(inputBufferIndex, 0,

mDestData.length, 0, 0);

}

MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();

int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,

0);

while (outputBufferIndex >= 0) {

ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];

byte[] outData = new byte[bufferInfo.size];

outputBuffer.get(outData);

try {

outputStream.write(outData, 0, outData.length);

} catch (Exception e) {

Log.d("AvcEncoder", "Outputstream write failed");

e.printStackTrace();

}

// Log.i("AvcEncoder", outData.length + " bytes written");

mediaCodec.releaseOutputBuffer(outputBufferIndex, false);

outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,

0);

}

} catch (Throwable t) {

t.printStackTrace();

}

}

}

通过Camera的startPreview调用此类:

private void startPreview() {

if (mCamera == null) {

return;

}

try {

mCamera.setPreviewDisplay(mSurfaceView.getHolder());

Parameters p = mCamera.getParameters();

Size s = p.getPreviewSize();

int len = s.width * s.height

* ImageFormat.getBitsPerPixel(p.getPreviewFormat()) / 8;

mAvcEncoder = new AvcEncoder(s.width, s.height);

mCamera.addCallbackBuffer(new byte[len]);

mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() {

@Override

public void onPreviewFrame(byte[] data, Camera camera) {

mAvcEncoder.offerEncoder(data);

mCamera.addCallbackBuffer(data);

}

});

mCamera.startPreview();

} catch (IOException e) {

e.printStackTrace();

}

}

释放相机时关闭它:

private void releaseCamera() {

if (mCamera != null) {

mCamera.stopPreview();

mCamera.release();

mCamera = null;

}

if (mAvcEncoder != null) {

mAvcEncoder.close();

}

}

总结

以上是生活随笔为你收集整理的android无法解码avcmp4,android - Android中的MediaCodec编码的H.264 avc视频无法播放 - 堆栈内存溢出...的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。