当我将视频解码到表面时,我想将我想要的帧保存为位图/ jpeg文件.我不想在屏幕上绘图,只想将SurfaceTexture的内容保存为图像文件.
我正在尝试使用MediaCodec从视频文件中获取所有帧.如果我尝试在SurfaceView上显示视频,一切正常.但是如果surface为null,并且当我尝试从字节数组中获取Bitmap时,alwaus将获得null或运行时异常.
这是我的代码:
private class PlayerThread extends Thread {
private MediaExtractor extractor;
private MediaCodec decoder;
private Surface surface;
public PlayerThread(Surface surface) {
this.surface = surface;
}
@Override
public void run() {
extractor = new MediaExtractor();
extractor.setDataSource(videoPath);
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
extractor.selectTrack(i);
decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, /*surface*/ null, null, 0);
break;
}
}
if (decoder == null) {
Log.e("DecodeActivity", "Can't find video info!");
return;
} …Run Code Online (Sandbox Code Playgroud) 我正在寻找有效的方法来减少一些视频权重(作为File上传),明显的答案是:让我们降低分辨率!(全高清或4K不需要,简单的高清对我来说已经足够了)我已经尝试了很多方法应该通过很多API(需要10),最好的方法是使用android-ffmpeg-java,但是...我的漂亮快速几乎当前的旗舰设备整个过程持续约length_of_video*4秒,此lib的重量是9 Mb,这个数量增加了我的应用程序大小...没有wai!(12 Mb到1 Mb是很好的结果,但仍然有太多的缺陷)
所以我决定使用原生的Android方式来实现这一点,MediaMuxer并且MediaCodec- 它们分别来自API18和API16(旧设备用户:抱歉;但他们也经常使用"低分辨率"相机).下面的方法几乎可以工作 - MediaMuxer不尊重MediaFormat.KEY_WIDTH和MediaFormat.KEY_HEIGHT- 提取File是"重新压缩",重量稍微小一点,但分辨率与原始视频相同File...
那么,问题:如何使用MediaMuxer和其他随附的类和方法压缩和重新调整/更改视频的分辨率?
public File getCompressedFile(String videoPath) throws IOException{
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(videoPath);
int trackCount = extractor.getTrackCount();
String filePath = videoPath.substring(0, videoPath.lastIndexOf(File.separator));
String[] splitByDot = videoPath.split("\\.");
String ext="";
if(splitByDot!=null && splitByDot.length>1)
ext = splitByDot[splitByDot.length-1];
String fileName = videoPath.substring(videoPath.lastIndexOf(File.separator)+1,
videoPath.length());
if(ext.length()>0)
fileName=fileName.replace("."+ext, "_out."+ext);
else
fileName=fileName.concat("_out");
final File outFile = new File(filePath, …Run Code Online (Sandbox Code Playgroud) 我目前正在使用Android Jelly Bean MediaCodec API来开发一个简单的视频播放器.
我在单独的线程中提取曲目,播放音频和视频.问题是视频播放总是播放太快.
哪里可以隐藏问题?
音频和视频的处理方式几乎相同,但音频通过AudioTrack播放,视频呈现在表面.
android surfaceview android-mediaplayer android-4.2-jelly-bean mediacodec
在BigFlake示例之后,有一条评论指出:
// Acquire a new frame of input, and render it to the Surface. If we had a
// GLSurfaceView we could switch EGL contexts and call drawImage() a second
// time to render it on screen. The texture can be shared between contexts by
// passing the GLSurfaceView's EGLContext as eglCreateContext()'s share_context
// argument.
Run Code Online (Sandbox Code Playgroud)
我EGL14.getCurrentContext()用来查询当前上下文并将其传递给EGL14.eglCreateContext()share_context参数,但是如何"切换EGL上下文"?
GLSurfaceView和MediaCodec.inputSurface有两个不同的表面和两个不同的上下文,所以我假设你只是eglMakeCurrent()单独调用每个集合,这是正确的吗?你需要eglDestroyContext()或eglDestroySurface()?
添加了更新
谢谢Fadden,我想我发现了这个错误,而不是drawFrame我调用了drawImage,但你不应该再次更新图像,对吧?
现在我glError 1285在设置EOS后调用dequeueBuffer时出现内存不足错误??? 也许我在录音停止后调用它.谢谢你的帮助.
在MyEGLWrapper.java中创建EGLSurface
saveToScreenRenderState();
mEGLContext = …Run Code Online (Sandbox Code Playgroud) 我正在寻找从MediaCodec解码器接收图像帧并将其绘制到Android设备屏幕的最快方法.重要的限制和解释是:
无法使用MediaPlayer.不允许使用中间应用.
必须尽快将MediaCodec解码器的输出帧绘制到屏幕上(最小化延迟).
可用的解码器输出格式如下:
ColorFormat [0] 0x00000013 COLOR_FormatYUV420Planar
ColorFormat [1] 0x00000015 COLOR_FormatYUV420SemiPlanar
ColorFormat [2] 0x7F000001 OMX_SEC_COLOR_FormatNV12TPhysicalAddress
ColorFormat [3] 0x7FC00002 OMX_SEC_COLOR_FormatNV12Tiled
视频分辨率以及每个输出帧的分辨率为960x720.
目标平台是Galaxy Note II,该方法可以特定于该平台(例如,利用可用的硬件功能).这不需要在其他平台上工作或者是通用解决方案.
一种不到66毫秒的方法会很好.不到33毫秒会很棒.我目前的方法需要80-90毫秒,这很糟糕.(我不打算去描述它,因为我不想在任何特定的方向上扭曲答案.)
我的目标是在Android中录制视频,并在录制时嵌入秒表.
我跟着的样品Grafika项目,CameraCaptureActivity.java他们使用OpenGL 2.0与录制视频录制为小块.他们使用以下代码在OpenGL 2.0中绘制块
private static void drawExtra()
{
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glScissor(0, 0, width / 3, height / 3);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码在录制和保存时在视频的左下方绘制了白色块.
我想要的是使用OpenGL 2.0 在白框上绘制文本,这样它也会与视频一起录制.
我不懂OpenGL 2.0.需要帮助才能在视频录制的同一表面上绘制文本,这样它就会像白盒一样嵌入到它中.
我想将本地保存的视频文件压缩到较小的尺寸,以便上传到服务器.
由于我使用了MediaCodec,我找到了一些压缩视频的技巧.以下是我遵循的步骤
1).使用MediaExrtactor提取媒体文件并对其进行解码.2).使用所需的文件格式创建编码器3).创建muxer以将文件保存在本地存储中.(未完成)
问题:但我不知道如何对已经解码的流进行编码,并使用MediaMuxer将流保存到本地存储中.
public class CompressMedia {
private static final String SAMPLE = Environment
.getExternalStorageDirectory() + "/DCIM/Camera/20140506_174959.mp4";
private static final String OUTPUT_PATH = Environment
.getExternalStorageDirectory()
+ "/DCIM/Camera/20140506_174959_REC.mp4";
private MediaExtractor extractor;
private MediaCodec decoder;
private MediaCodec encoder;
String mime;
private static final String MIME_TYPE = "video/avc";
public void extractMediaFile() {
// work plan
// locate media file
// extract media file using Media Extractor
// retrieve decoded frames
extractor = new MediaExtractor();
try {
extractor.setDataSource(SAMPLE);
} catch (IOException e) { …Run Code Online (Sandbox Code Playgroud) 问题:我有来自GoPro相机的视频流,格式为.m3u8.我需要在应用程序中显示流的内容,然后流式传输视频.对于流媒体,我有与MediaCodec和ffmpeg一起使用的库.我应该能够流式传输MediaCodec的outputBuffer.
我可以在SurfaceView上使用MediaPlayer流式传输视频,没问题.真正的困难在于使用MediaCodec.我可以初始化MediaCodec,获取表面并将其添加到MediaPlayer - 蒸汽播放 - 我可以听到声音.
现在的问题是:
在SurfaceView上显示流 - 或MP和MC可以使用的任何其他视图.从Surface到SurfaceView/TextureView显示数据的最佳方法是什么?
我无法从MediaCodec获取数据.我只需要支持5.0+设备,所以我尝试使用MediaCodec.Callback.但我每次都会得到错误.我还没有找到错误的含义.我可以做些什么来配合Callback工作?
有没有"简单"的方法,或者我必须深入到谷歌Grafika的缓冲区和表面?
以下是我得到的错误:
E/ACodec? [OMX.qcom.video.encoder.avc] storeMetaDataInBuffers (output) failed w/ err -2147483648
1877-1904/com.example.marek.goprorecorder E/ACodec? [OMX.qcom.video.encoder.avc] ERROR(0x80001009)
07-15 15:54:47.411 1877-1904/com.example.marek.goprorecorder E/ACodec? signalError(omxError 0x80001009, internalError -2147483648)
07-15 15:54:47.411 1877-1903/com.example.marek.goprorecorder E/MediaCodec? Codec reported err 0x80001009, actionCode 0, while in state 6
Errror mess: android.media.MediaCodec$CodecException: Error 0x80001009
07-15 15:54:47.454 1877-1877/com.example.marek.goprorecorder D/MediaCodecCallback? Errror diag: android.media.MediaCodec.error_neg_2147479543
07-15 15:54:47.454 1877-1877/com.example.marek.goprorecorder D/MediaCodecCallback? Errror rec: false
07-15 15:54:47.454 1877-1877/com.example.marek.goprorecorder D/MediaCodecCallback? Errror tra: false
Run Code Online (Sandbox Code Playgroud)
这是我的活动:
public class MainActivity extends ActionBarActivity implements …Run Code Online (Sandbox Code Playgroud) 通过Android中的MediaCodec进行编码时,我正在登录logcat下一个错误.
实际编码工作正常,输出正确生成,所以我真的不明白为什么我得到这个跟踪.这是一个无害的错误痕迹,还是我缺少的东西?
E/ACodec(6438):[OMX.qcom.video.encoder.h263] storeMetaDataInBuffers(输出)失败w/err -1010
接下来是我得到跟踪的代码
final int BIT_RATE = 4000000;
final int FRAME_RATE = 30;
final int IFRAME_INTERVAL = 5;
final String MIME_TYPE = "video/avc";
final MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
MediaCodec encoder = MediaCodec.createEncoderByType(MIME_TYPE);
//---------------------------------
// NEXT LINE PRODUCES THE TRACE
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
//---------------------------------
Run Code Online (Sandbox Code Playgroud) android ×10
mediacodec ×10
video ×3
decoder ×2
opengl-es ×2
surfaceview ×2
bitmap ×1
compression ×1
decode ×1
egl ×1
encode ×1
encoding ×1
java ×1
mediamuxer ×1
yuv ×1