我使用 MediaExtractor 和 MediaCodec 成功解码并播放了 mp4 (AAC) 文件,代码如下。我想将原始 AAC(在另一个文件中,具有相同的编码格式)解码为 PCM。问题是我不知道如何在没有 mediaExtractor 的情况下设置SampleSize和presentationTimeUs。如何在不使用 MediaExtractor 的情况下设置上述参数?
//songwav.mp4 文件是用这种格式从 PCM 创建的
MediaFormat outputFormat = MediaFormat.createAudioFormat(
"audio/mp4a-latm", 44100, 2);
outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel.AACObjectLC);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE,
128000);
Run Code Online (Sandbox Code Playgroud)
//解码
String inputfilePath = Environment.getExternalStorageDirectory()
.getPath() + "/" + "songwav.mp4";
String outputFilePath = Environment.getExternalStorageDirectory()
.getPath() + "/" + "songwavmp4.pcm";
OutputStream outputStream = new FileOutputStream(outputFilePath);
MediaCodec codec;
AudioTrack audioTrack;
// extractor gets information about the stream
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(inputfilePath);
MediaFormat format = extractor.getTrackFormat(0);
String mime …Run Code Online (Sandbox Code Playgroud) “MediaCodec 解码器可以使用上述格式之一或专有格式在 ByteBuffers 中生成数据。例如,基于 Qualcomm SoC 的设备通常使用 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m (#2141391876 / 0x7FA30C04)。”
这使得处理输出缓冲区变得困难甚至无法处理。为什么不使用统一的YUV格式?为什么有这么多YUV颜色格式?
@fadden,我发现可以解码到 Surface 并获取 RGB 缓冲区(如http://bigflake.com/mediacodec/ExtractMpegFramesTest.java.txt),我可以将 RGB 缓冲区传输为 YUV 格式然后对其进行编码吗?
而且,fadden,我尝试使用 API 18+ 并遇到了一些问题。我参考了 ContinuousCaptureActivity 和 ExtractMpegFramesTest 代码。在ContinuousCaptureActivity中:
mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
mDisplaySurface = new WindowSurface(mEglCore, holder.getSurface(), false);
mDisplaySurface.makeCurrent();
mFullFrameBlit = new FullFrameRect(
new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));
mTextureId = mFullFrameBlit.createTextureObject();
mCameraTexture = new SurfaceTexture(mTextureId);
mCameraTexture.setOnFrameAvailableListener(this);
mCamera.setPreviewTexture(mCameraTexture);
Run Code Online (Sandbox Code Playgroud)
FullFrameRect 创建一个 SurfaceTexture 并将其设置为相机预览纹理。
但是在 ExtractMpegFramesTest 中,使用了 CodecOutputSurface 并且它还创建了一个纹理。我怎样才能一起使用 CodecOutputSurface 和 FullFrameRect?(一个提供表面来接收解码器输出,一个重新缩放并渲染到编码器输入表面。)
我想使用 NDK 和 opengl 在后台(无 UI)中分析视频。我想解码视频并在纹理(内存)上渲染。我们怎么做?
我尝试使用 AMediaCodec 直接在纹理上渲染。但问题是它需要 ANativeWindow(在 AMediaCodec_configure 中),我无法从 opengl 纹理(使用 glGenTextures 创建)创建它。任何人都可以请建议吗?
我正在尝试在设备之间流式传输视频。我想尽可能支持旧设备。所以我从MediaRecorderGingerbread (API 10) 的课程开始,但它有问题。所以现在,我要转向 Jelly Bean (API 16) 和MediaCodec.
我正在向 Camera 中的编解码器提供数据PreviewCallback。我必须使用相同的分辨率进行预览和编解码器。但是在我们的一些测试设备上,预览分辨率和编解码器及其分辨率之间没有交集。
那么,如何在这些设备上捕捉视频呢?我知道有 createInputSurfacein MediaCodec,但它需要 API 18,我将不得不削减超过 35%的设备,这是不可接受的。
那么如何解决呢?
寻找最佳分辨率的代码:
CamcorderProfile bestProfile() {
final int[] profiles;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
profiles = new int[]{CamcorderProfile.QUALITY_HIGH, CamcorderProfile.QUALITY_2160P, CamcorderProfile.QUALITY_1080P, CamcorderProfile.QUALITY_720P, CamcorderProfile.QUALITY_480P, CamcorderProfile.QUALITY_CIF, CamcorderProfile.QUALITY_QCIF, CamcorderProfile.QUALITY_LOW};
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
profiles = new int[]{CamcorderProfile.QUALITY_HIGH, CamcorderProfile.QUALITY_1080P, CamcorderProfile.QUALITY_720P, CamcorderProfile.QUALITY_480P, CamcorderProfile.QUALITY_CIF, CamcorderProfile.QUALITY_QCIF, CamcorderProfile.QUALITY_LOW};
} else {
profiles = new int[]{CamcorderProfile.QUALITY_HIGH, CamcorderProfile.QUALITY_LOW};
}
for (final …Run Code Online (Sandbox Code Playgroud) 我正在尝试从一系列位图创建电影。我想以 API 19 为目标,但也可以利用 API 21(如果它在设备上可用)。
我一直在阅读 bigflake CTS 测试,尤其是这里的EncodeAndMux 和 EncodeDecodeTest
我想使用 MediaCodec 和 MediaMuxer 类,而不是 FFMpeg 或 Jcodec 等。
如果您能指出我哪里出错以及如何解决,我将不胜感激。我是 Android 新手,为此苦苦挣扎了好几天!我正在三星 Galaxy Note 3 上进行测试
更新:我能够访问 EOS,但在尝试释放编码器时出现编解码器错误。
这是更新后的代码:
public void createMovie(View view) {
Log.v(TAG,"CREATING MOVIE");
//1. Prepare the encoder and the GPUImageView
try {
prepareEncoder();
presentationTime = 0;
int j = 0;
for (int i = firstImageIndex; i <= lastImageIndex; i++) {
Log.v(TAG, "inLoop: " + i);
//1
durationInNanosec = (long) ((float) durations.get(j) * 100000); …Run Code Online (Sandbox Code Playgroud) 我从:http ://bigflake.com/mediacodec/开始,EncodeAndMuxTest 示例。使用opengl生成帧。我更改了 generateSurfaceFrame() 方法,如下所示:
private void generateSurfaceFrame(int frameIndex)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
// decode image to bitmap
final Bitmap bitmap = BitmapFactory.decodeFile("PathToMyImage.jpg");
GLES20.glEnable(GL10.GL_TEXTURE_2D);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
} …Run Code Online (Sandbox Code Playgroud) 尝试配置 AVC 编码器时收到异常。当视频流分辨率发生变化时,我需要关闭并重新创建编解码器。有没有人有以下异常的输入:
10-14 15:10:20.934 E/OMX-VENC( 980): async_venc_message_thread interrupted to be exited
10-14 15:10:20.944 I/OMX-VENC( 980): Component Deinit
10-14 15:10:20.944 I/OMX-VENC( 980): Video encode perflock released
10-14 15:10:20.944 I/ACodec ( 3824): [OMX.qcom.video.encoder.avc] Now uninitialized
10-14 15:10:20.944 I/ACodec ( 3824): [] Now kWhatShutdownCompleted event : 7062
10-14 15:10:20.944 I/MediaCodec( 3824): Codec shutdown complete
10-14 15:10:20.944 I/ACodec ( 3824): [] Now uninitialized
10-14 15:10:20.944 I/ACodec ( 3824): [] onAllocateComponent
10-14 15:10:20.944 I/OMXClient( 3824): Using client-side OMX mux.
10-14 15:10:20.954 I/OMX-VENC( 980): Video …Run Code Online (Sandbox Code Playgroud) 我正在使用 MediaProjection API 创建屏幕录像机应用程序。在我的应用程序中,我将停止按钮显示为一个小的覆盖窗口。我一直保持这个视图的安全,这样它就不会出现在最终录制的视频中。
此视图不会出现在最终视频中,但最终输出本身就是一个黑色区域,而不是原始视图。
有没有办法在没有这个黑色区域的情况下获得最终的视频输出?
android surfaceview android-mediaprojection android-mediacodec
我正在尝试从 Android 相机(由 MediaCodec 编码)捕获 h264 帧并将它们传递给在同一设备上运行的 FFmpeg 进程。
我目前通过将我从 MediaCodec 接收到的编码字节数组写入名为 out.h264 的文件来实现。
像这样:
FileOutputStream fosVideo = new ...
...
// encoder callback
@Override
public void onVideoData(ByteBuffer h264Buffer, MediaCodec.BufferInfo info) {
fosVideo.write(h264Buffer);
}
Run Code Online (Sandbox Code Playgroud)
在写入 h264 文件时,我启动 FFmpeg 进程并提供 h264 文件作为输入。
ffmpeg -re -i out.h264 -c:v copy -r 30 -loglevel 48 a.mp4
Run Code Online (Sandbox Code Playgroud)
我也试过
ffmpeg -re -framerate 25 -i out.h264 -c:v copy -r 30 -loglevel 48 a.mp4
Run Code Online (Sandbox Code Playgroud)
FFmpeg 进程在 10 秒到几分钟之间运行,然后突然停止:
frame= 330 fps= 29 q=31.0 size= 512kB time=00:00:10.98 bitrate= 381.8kbits/s …Run Code Online (Sandbox Code Playgroud) 我们有原始流数据,我们使用 Kitkat 上的 MediaCodec 本机代码对其进行解码和渲染。
考虑我们的视频分辨率为 800 X 480,实际视频内容为 800 X 380。顶部和底部高度边距各 50 像素包含黑色区域。在表面上渲染时需要裁剪黑色区域(100 像素)。
尝试了 setRect 方法来裁剪矩形,但没有奏效。
例子:
int32_t left, top, right, bottom;
if (format->findRect("crop", &left, &top, &right, &bottom))
{
left = 0, top = 100, right = 800, bottom = 380;
format->setRect("crop", left, top, right, bottom);
}
Run Code Online (Sandbox Code Playgroud)
另外,尝试在配置格式时设置Mediacodec中指定的crop-left,crop-right,crop-top,crop-bottom,这也未能裁剪。例子:
format.setInteger("crop-left", 0);
format.setInteger("crop-top", 100);
format.setInteger("crop-right", 800);
format.setInteger("crop-bottom", 380);
Run Code Online (Sandbox Code Playgroud)
您能否提出一种裁剪视频的方法,以便裁剪后的视频可以在表面上呈现。
android ×9
aac ×1
android-ndk ×1
audio ×1
crop ×1
ffmpeg ×1
h.264 ×1
mediamuxer ×1
opengl-es ×1
surfaceview ×1
video ×1
yuv ×1