引用JNI版本----MediaMetadataRetriever获取视频缩略图(真机4.0测试通过)
来源:互联网 发布:图像算法工程师 知乎 编辑:程序博客网 时间:2024/06/12 18:11
在 DDMS-file browser-system-lib导出jni库函数:libmedia_jni.so
然后在android项目中libs文件夹下面建立armeabi文件夹并把库函数拷贝进来;
然后创建一个android.media包(必须要在这个包下创建,否则出错),并创建MediaMetadataRetriever类,我在网上找到的这个类,Android 视频缩略图之MediaMetadataRetriever
有些方法已经不存在了,应该是版本问题,
没办法我只好看源码的jni(frameworks\base\media\jni)文件,看了之后知道有哪些函数,但是因为没接触过jni,所以要传哪些参数都没看懂,所以偷懒了
去android developers看了API(猛击这里),这样也确认了API的正确,也知道如何传参。
这样我重新在从网上获取到的这个类(MediaMetadataRetriever),再加上几行简单的 native 函数声明就简单粗暴的解决了我的问题。。
之所以导入jni库来获取缩略图是为了不用考虑版本问题,或者说简化维护版本问题。。
在android.media包下的代码:
package android.media;//package android.media;import java.io.FileDescriptor;import java.io.FileNotFoundException;import java.io.IOException;import android.content.ContentResolver;import android.content.Context;import android.content.res.AssetFileDescriptor;import android.graphics.Bitmap;import android.net.Uri;/*** MediaMetadataRetriever class provides a unified interface for retrieving* frame and meta data from an input media file.* {@hide}*/public class MediaMetadataRetriever{ static { System.loadLibrary("media_jni"); } // The field below is accessed by native methods @SuppressWarnings("unused") private int mNativeContext; public MediaMetadataRetriever() { native_setup(); } /** * Call this method before setDataSource() so that the mode becomes * effective for subsequent operations. This method can be called only once * at the beginning if the intended mode of operation for a * MediaMetadataRetriever object remains the same for its whole lifetime, * and thus it is unnecessary to call this method each time setDataSource() * is called. If this is not never called (which is allowed), by default the * intended mode of operation is to both capture frame and retrieve meta * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY). * Often, this may not be what one wants, since doing this has negative * performance impact on execution time of a call to setDataSource(), since * both types of operations may be time consuming. * * @param mode The intended mode of operation. Can be any combination of * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY: * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: * For neither frame capture nor meta data retrieval * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: * For both frame capture and meta data retrieval */ public native void setMode(int mode); /** * @return the current mode of operation. A negative return value indicates * some runtime error has occurred. */ public native int getMode(); /** * Sets the data source (file pathname) to use. Call this * method before the rest of the methods in this class. This method may be * time-consuming. * * @param path The path of the input media file. * @throws IllegalArgumentException If the path is invalid. */ public native void setDataSource(String path) throws IllegalArgumentException; /** * Sets the data source (FileDescriptor) to use. It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon * as this call returns. Call this method before the rest of the methods in * this class. This method may be time-consuming. * * @param fd the FileDescriptor for the file you want to play * @param offset the offset into the file where the data to be played starts, * in bytes. It must be non-negative * @param length the length in bytes of the data to be played. It must be * non-negative. * @throws IllegalArgumentException if the arguments are invalid */ public native void setDataSource(FileDescriptor fd, long offset, long length) throws IllegalArgumentException; /** * Sets the data source (FileDescriptor) to use. It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon * as this call returns. Call this method before the rest of the methods in * this class. This method may be time-consuming. * * @param fd the FileDescriptor for the file you want to play * @throws IllegalArgumentException if the FileDescriptor is invalid */ public void setDataSource(FileDescriptor fd) throws IllegalArgumentException { // intentionally less than LONG_MAX setDataSource(fd, 0, 0x7ffffffffffffffL); } /** * Sets the data source as a content Uri. Call this method before * the rest of the methods in this class. This method may be time-consuming. * * @param context the Context to use when resolving the Uri * @param uri the Content URI of the data you want to play * @throws IllegalArgumentException if the Uri is invalid * @throws SecurityException if the Uri cannot be used due to lack of * permission. */ public void setDataSource(Context context, Uri uri) throws IllegalArgumentException, SecurityException { if (uri == null) { throw new IllegalArgumentException(); } String scheme = uri.getScheme(); if(scheme == null || scheme.equals("file")) { setDataSource(uri.getPath()); return; } AssetFileDescriptor fd = null; try { ContentResolver resolver = context.getContentResolver(); try { fd = resolver.openAssetFileDescriptor(uri, "r"); } catch(FileNotFoundException e) { throw new IllegalArgumentException(); } if (fd == null) { throw new IllegalArgumentException(); } FileDescriptor descriptor = fd.getFileDescriptor(); if (!descriptor.valid()) { throw new IllegalArgumentException(); } // Note: using getDeclaredLength so that our behavior is the same // as previous versions when the content provider is returning // a full file. if (fd.getDeclaredLength() < 0) { setDataSource(descriptor); } else { setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength()); } return; } catch (SecurityException ex) { } finally { try { if (fd != null) { fd.close(); } } catch(IOException ioEx) { } } setDataSource(uri.toString()); } /** * Call this method after setDataSource(). This method retrieves the * meta data value associated with the keyCode. * * The keyCode currently supported is listed below as METADATA_XXX * constants. With any other value, it returns a null pointer. * * @param keyCode One of the constants listed below at the end of the class. * @return The meta data value associate with the given keyCode on success; * null on failure. */ public native String extractMetadata(int keyCode); /** * Call this method after setDataSource(). * This method finds a representative frame at any time position if possible, * and returns it as a bitmap. T * his is useful for generating a thumbnail for an input data source. * Call this method if one does not care about where the frame is located; * @return A Bitmap containing a representative video frame, * which can be null, if such a frame cannot be retrieved. */ public native Bitmap getFrameAtTime(); /** * Call this method after setDataSource(). This method finds a * representative frame if successful and returns it as a bitmap. This is * useful for generating a thumbnail for an input media source. * * @return A Bitmap containing a representative video frame, which * can be null, if such a frame cannot be retrieved. */ public native Bitmap captureFrame(); /** * Call this method after setDataSource(). This method finds the optional * graphic or album art associated (embedded or external url linked) the * related data source. * * @return null if no such graphic is found. */ public native byte[] extractAlbumArt(); /** * Call it when one is done with the object. This method releases the memory * allocated internally. */ public native void release(); private native void native_setup(); private native final void native_finalize(); @Override protected void finalize() throws Throwable { try { native_finalize(); } finally { super.finalize(); } } public static final int MODE_GET_METADATA_ONLY = 0x01; public static final int MODE_CAPTURE_FRAME_ONLY = 0x02; /* * Do not change these values without updating their counterparts * in include/media/mediametadataretriever.h! */ public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; public static final int METADATA_KEY_ALBUM = 1; public static final int METADATA_KEY_ARTIST = 2; public static final int METADATA_KEY_AUTHOR = 3; public static final int METADATA_KEY_COMPOSER = 4; public static final int METADATA_KEY_DATE = 5; public static final int METADATA_KEY_GENRE = 6; public static final int METADATA_KEY_TITLE = 7; public static final int METADATA_KEY_YEAR = 8; public static final int METADATA_KEY_DURATION = 9; public static final int METADATA_KEY_NUM_TRACKS = 10; public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11; public static final int METADATA_KEY_CODEC = 12; public static final int METADATA_KEY_RATING = 13; public static final int METADATA_KEY_COMMENT = 14; public static final int METADATA_KEY_COPYRIGHT = 15; public static final int METADATA_KEY_BIT_RATE = 16; public static final int METADATA_KEY_FRAME_RATE = 17; public static final int METADATA_KEY_VIDEO_FORMAT = 18; public static final int METADATA_KEY_VIDEO_HEIGHT = 19; public static final int METADATA_KEY_VIDEO_WIDTH = 20; // Add more here...}
在另一个java包(com.example.thumbnaildemo)中的代码:
package com.example.thumbnaildemo;import java.io.File;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.content.ContentResolver;import android.database.Cursor;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.media.MediaMetadataRetriever;import android.media.ThumbnailUtils;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.provider.MediaStore.Video;import android.text.format.DateFormat;import android.util.Log;import android.widget.ImageView;public class MainActivity extends Activity { final static String TAG = "MainActivity";ImageView thumbnails;@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.i(TAG,"------------------onCreate---------------------------");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thumbnails=(ImageView)findViewById(R.id.imageView2);/*InputStream input = getResources().openRawResource(R.drawable.girl); BitmapDrawable girl = new BitmapDrawable(input); Bitmap bitmap = girl.getBitmap(); bitmap =ThumbnailUtils.extractThumbnail(bitmap, 50, 50); thumbnails.setImageBitmap(bitmap);*/ File file = new File("/sdcard/mp4/china.mp4"); Bitmap bitmap = createVideoThumbnail(file.getAbsolutePath()); thumbnails.setImageBitmap(bitmap);/*List<Video> allVideoList = null;// 视频信息集合allVideoList = new ArrayList<Video>();getVideoFile(allVideoList);// 获得视频文件*/ }private void getVideoFile(final List<Video> list) { Bitmap bitmap = null; ContentResolver mContentResolver = this.getContentResolver(); Cursor cursor = mContentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Video.DEFAULT_SORT_ORDER); Log.i(TAG,"------------------getVideoFile---------------------------"); if (cursor.moveToFirst()) { Log.i(TAG,"------------------getVideoFile-----cursor.moveToFirst----------------------"); //do { //ID:MediaStore.Audio.Media._ID int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)); //名称 :MediaStore.Audio.Media.TITLE String tilte = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE)); //专辑名:MediaStore.Audio.Media.ALBUM String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.ALBUM)); //歌手名: MediaStore.Audio.Media.ARTIST String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.ARTIST)); //路径 :MediaStore.Audio.Media.DATA String url = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)); //总播放时长 :MediaStore.Audio.Media.DURATION int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)); //大小 :MediaStore.Audio.Media.SIZE int size = (int)cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)); //拍摄时间 int dateTaken = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_TAKEN)); String datetime = DateFormat.format("yyyy-MM-dd kk:mm:ss", dateTaken).toString(); bitmap = createVideoThumbnail(url); thumbnails.setImageBitmap(bitmap); } }/** * @param filePath * @return */private Bitmap createVideoThumbnail(String filePath) {Log.i(TAG,"------------------createVideoThumbnail---------------------------"); Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { //retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); retriever.setDataSource(filePath); //bitmap = retriever.captureFrame(); bitmap= retriever.getFrameAtTime(); } catch(IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { // Assume this is a corrupt video file. } finally { try { retriever.release(); } catch (RuntimeException ex) { // Ignore failures while cleaning up. } } return bitmap; } }
0 0
- 未引用JNI版本----MediaMetadataRetriever获取视频缩略图(真机4.0测试通过)
- 引用JNI版本----MediaMetadataRetriever获取视频缩略图(真机4.0测试通过)
- 使用 MediaMetadataRetriever类获取视频缩略图
- Android 视频缩略图之MediaMetadataRetriever
- 通过路径获取视频 缩略图
- MediaMetadataRetriever获取视频第一帧失败
- android MediaMetadataRetriever获取的缩略图有些是全黑的
- MediaMetadataRetriever的使用 (一) 获取视频正确宽高的小问题
- android 获取网络视频缩略图【完美兼容各版本】
- android 获取网络视频缩略图【完美兼容各版本
- android 获取网络视频缩略图【完美兼容各版本】
- android 通过文件名获取SD卡视频缩略图
- android MediaMetadataRetriever 获取视频宽高及时长例子
- Android之使用MediaMetadataRetriever类获取视频第一帧
- 获取视频缩略图
- 获取视频缩略图
- IOS获取视频缩略图
- 获取视频缩略图
- Linux输入子系统:输入设备编程指南 -- input-programming.txt
- github push 出现connection refused 的处理办法
- crontab实用手册
- 信息节点的自定义配置实验
- Gson简要使用笔记
- 引用JNI版本----MediaMetadataRetriever获取视频缩略图(真机4.0测试通过)
- mysql优化
- Shell 显示带颜色字体
- 谈谈ANDROID反编译和防止反编译的方法(转)
- 项目六:穷举法解决组合问题(5)委派任务
- 油价暴跌对产油国的影响
- iPhone数据持久化
- PHP中使用cURL实现Get和Post请求的方法
- HDU 2795 BillBoard 线段树