关于havlenapetr-FFMpeg在Android 4.0(ICS)的补充说明
来源:互联网 发布:求最小公倍数算法 编辑:程序博客网 时间:2024/04/29 02:20
/********************************************************************************************
* author:conowen@大钟
* E-mail:conowen@hotmail.com
* http://blog.csdn.net/conowen
* 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。
********************************************************************************************/
之前的这篇博文http://blog.csdn.net/conowen/article/details/7526398
所提及到的framework/base/native文件夹下面的audio与vedio文件夹可以在https://github.com/havlenapetr/android_frameworks_base
然而,对于Android 4.0(ICS),上述的地址中的ICS分支对于原本的FFmpeg工程显然是不能对接得上的,虽然可以在Android 4.0 的source code中编译通过,但是这个分支的surface.cpp中定义的方法与FFmpeg的JNI方法对应不上。
@Android 4.0 ICS的surface.cpp
/* * Copyright (C) 2012 Havlena Petr * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#define LOG_TAG "ASurface"#include <utils/Log.h>#include <surfaceflinger/Surface.h>#include <SkCanvas.h>#include <SkBitmap.h>#include <SkMatrix.h>#include <SkRect.h>#include "surface.h"#define CHECK(val) \ if(!val) { \ LOGE("%s [%i]: NULL pointer exception!", __func__, __LINE__); \ return -1; \ }#define SDK_VERSION_FROYO 8using namespace android;typedef struct ASurface { /* our private members here */ Surface* surface; SkCanvas canvas;} ASurface;static Surface* getNativeSurface(JNIEnv* env, jobject jsurface, int sdkVersion) { /* we know jsurface is a valid local ref, so use it */ jclass clazz = env->GetObjectClass(jsurface); if(clazz == NULL) { LOGE("Can't find surface class!"); return NULL; } jfieldID field_surface = env->GetFieldID(clazz, sdkVersion > SDK_VERSION_FROYO ? "mNativeSurface" : "mSurface", "I"); if(field_surface == NULL) { LOGE("Can't find native surface field!"); return NULL; } return (Surface *) env->GetIntField(jsurface, field_surface);}int ASurface_init(JNIEnv* env, jobject jsurface, int sdkVersion, ASurface** aSurface) { if(!env || jsurface == NULL) { LOGE("JNIEnv or jsurface obj is NULL!"); return -1; } Surface* surface = getNativeSurface(env, jsurface, sdkVersion); if(!surface) { LOGE("Can't obtain native surface!"); return -1; } *aSurface = (ASurface *) malloc(sizeof(ASurface)); (*aSurface)->surface = surface; return 0;}void ASurface_deinit(ASurface** aSurface) { free(*aSurface); *aSurface = NULL;}int ASurface_lock(ASurface* aSurface, AndroidSurfaceInfo* info) { static Surface::SurfaceInfo surfaceInfo; CHECK(aSurface); CHECK(aSurface->surface); Surface* surface = aSurface->surface; if (!surface->isValid()) { LOGE("Native surface isn't valid!"); return -1; } int res = surface->lock(&surfaceInfo); if(res < 0) { LOGE("Can't lock native surface!"); return res; } info->w = surfaceInfo.w; info->h = surfaceInfo.h; info->s = surfaceInfo.s; info->usage = surfaceInfo.usage; info->format = surfaceInfo.format; info->bits = surfaceInfo.bits; return 0;}static SkBitmap::ConfigconvertPixelFormat(APixelFormat format) { switch(format) { case ANDROID_PIXEL_FORMAT_RGBX_8888: case ANDROID_PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; case ANDROID_PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; } return SkBitmap::kNo_Config;}static voidinitBitmap(SkBitmap& bitmap, AndroidSurfaceInfo* info) { bitmap.setConfig(convertPixelFormat(info->format), info->w, info->h); if (info->format == ANDROID_PIXEL_FORMAT_RGBX_8888) { bitmap.setIsOpaque(true); } if (info->w > 0 && info->h > 0) { bitmap.setPixels(info->bits); } else { // be safe with an empty bitmap. bitmap.setPixels(NULL); }}void ASurface_scaleToFullScreen(ASurface* aSurface, AndroidSurfaceInfo* src, AndroidSurfaceInfo* dst) { SkBitmap srcBitmap; SkBitmap dstBitmap; SkMatrix matrix; initBitmap(srcBitmap, src); initBitmap(dstBitmap, dst); matrix.setRectToRect(SkRect::MakeWH(srcBitmap.width(), srcBitmap.height()), SkRect::MakeWH(dstBitmap.width(), dstBitmap.height()), SkMatrix::kFill_ScaleToFit); aSurface->canvas.setBitmapDevice(dstBitmap); aSurface->canvas.drawBitmapMatrix(srcBitmap, matrix);}int ASurface_rotate(ASurface* aSurface, AndroidSurfaceInfo* src, uint32_t degrees) { SkBitmap bitmap; CHECK(aSurface); CHECK(src); initBitmap(bitmap, src); aSurface->canvas.setBitmapDevice(bitmap); return aSurface->canvas.rotate(SkScalar(degrees)) ? 0 : -1;}int ASurface_unlockAndPost(ASurface* aSurface) { CHECK(aSurface); CHECK(aSurface->surface); return aSurface->surface->unlockAndPost();}
@Z:\projects\ffmpeg\jni\libmediaplayer\output.cpp(视频输出接口部分)
//-------------------- Video driver --------------------//这四个接口都没有在surface.cpp里面定义 int Output::VideoDriver_register(JNIEnv* env, jobject jsurface){return AndroidSurface_register(env, jsurface);}int Output::VideoDriver_unregister(){return AndroidSurface_unregister();}int Output::VideoDriver_getPixels(int width, int height, void** pixels){return AndroidSurface_getPixels(width, height, pixels);}int Output::VideoDriver_updateSurface(){return AndroidSurface_updateSurface();}
但是,我们依然可以把Android 2.3 (Gingerbread)中的video模块一样地移植到Android 4.0(ICS)中去,因为这个分支的surface.cpp的方法依然可以和JNI对接上。
编译步骤可以参考之前的博文,这里不再赘述。
但是在ICS的机器上面运行此播放器时,可能会提示以下errors。(Surface::lock failed, already locked)
08-16 21:46:41.863: E/FFMpegMediaPlayer(2263): waiting on video thread08-16 21:46:41.873: I/FFMpegVideoDecoder(2263): videoclock----> 6.68000008-16 21:46:41.883: E/SurfaceTextureClient(2263): Surface::lock failed, already locked08-16 21:46:41.893: I/FFMpegVideoDecoder(2263): videoclock----> 6.72000008-16 21:46:41.913: E/SurfaceTextureClient(2263): Surface::lock failed, already locked
这和机器的ROM有关系。因为Android 4.0(ICS)中的libsurfaceflinger.so库没有具体的内容,视频输出有关的surface操作函数由libgui.so完成。而有些SDK对gui库进行改动了。所以把Google官方源码包中的framework/base/libs/gui文件夹和framework/base/include/gui文件夹面的gui库代替机器的SDK中的gui包,重新编译生成ROM,即可正常播放。
附上个人编译修改的播放器:
1、实现了在Android 2.3 和Android 4.0各个平台上面的播放。
2、多格式支持
3、音视频基本同步
4、支持跳转(seek)、暂停、快进、快退、尺寸缩放等等。
5、没开启neon硬件加速时,480P的视频基本流畅播放。
- 关于havlenapetr-FFMpeg在Android 4.0(ICS)的补充说明
- 关于havlenapetr-FFMpeg在Android 4.0(ICS)的补充说明
- 移植havlenapetr的ffmpeg-->Android播放器
- 移植havlenapetr的ffmpeg-->Android播放器
- havlenapetr-FFMpeg OnVideoSizeChangedListener接口的实现
- havlenapetr-FFMpeg OnVideoSizeChangedListener接口的实现
- Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg
- 移植FFmpeg到android ics
- 移植FFmpeg到android ics
- 关于留言簿的补充说明
- 关于#include的补充说明
- 关于private的补充说明
- 编译android 4.0 (ICS)
- Havlenapetr/FFMpeg编译
- havlenapetr-FFMpeg实现OnVideoSizeChangedListener
- FFMpeg havlenapetr工程编译
- havlenapetr/FFMpeg 好像是2年前的啊。
- Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg-7c27aa2
- 线程初始化和锁
- 将文件压缩为zip格式
- 反恐精英便携版 Critical Strike Portable
- 对于自己,唯有努力
- 为notepad配置vs环境
- 关于havlenapetr-FFMpeg在Android 4.0(ICS)的补充说明
- 短信猫发送SQL Server数据库和加密狗在VM虚拟机上识别
- 用Java压缩文件后再用web service实现下载传送
- navicat 10.1.3 注册码 中英文
- unity3.5新粒子系统入门分享。。。一二合集。。。
- 关于指针数组的小练习
- HDU 4379 - The More The Better
- 使用minidom来处理XML的示例(Python 学习)
- 如何在eclipse里查看android源码