将这个“fmmr-demo”下的android工程导入eclipse下看一下他的代码是如何实现加载视频的略缩图的,其实现代码如下:

FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();
try {
	fmmr.setDataSource(mUri);
	for (int i = 0; i < Constants.METADATA_KEYS.length; i++) {
		String key = Constants.METADATA_KEYS[i];
		String value = fmmr.extractMetadata(key);
		if (value != null) {
			 metadata.add(new Metadata(key, value));
			 Log.i(MetadataLoader.class.getName(), "Key: " + key + " Value: " + value);
		}
	}
	Bitmap b = fmmr.getFrameAtTime();
	if (b != null) {
		Bitmap b2 = fmmr.getFrameAtTime(4000000,FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC);
		if (b2 != null) {
		b = b2;
		}
	}
} catch(Exception e){
}

中间有些代码不用去看,只需要关心三行代码并且在源码FFmpegMediaMetadataRetriever.java中有详细解释:

  • fmmr.setDataSource(mUri);
    设置视频的来源,在其他的方法之前调用,并且这个方法可能耗时。
  • Bitmap b = fmmr.getFrameAtTime();
    这个方法在setDataSource后面调用,并且这个方法获取任意一帧的图像,并且返回bitmap,对于获取略缩图所在的时间点没有限制的话,这个方法是有用的,否则调用其他带参数的方法。
  • Bitmap b2 = fmmr.getFrameAtTime(4000000,FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC)
    函数在源码中的原型是public Bitmap getFrameAtTime(long timeUs, int option),解释如下:在setDataSource()后面调用这个方法,在尽可能考虑给予的条件限制下找到靠近时间点的一帧图像并返回Bitmap,这个方法用来生成视频资源的略缩图或者用来获取和展示某个时间的一帧图像。
timeUs
  • 这个时间点的帧将会被获取到,但是不能保证视频资源在这个时间的位置有一帧图像,如果没有,那么这个时间点附近的一帧图像将会被返回。如果这个参数为负数,那么这个函数中的两个参数的中将会被忽略,并且返回任意一帧的图像。
option
  • 获取帧图像的方式:
    OPTION_PREVIOUS_SYNC,在给予的时间戳之前获取同步帧
    OPTION_NEXT_SYNC,在给予的时间戳之后获取同步帧
    OPTION_CLOSEST_SYNC,在给予的时间戳附近
    OPTION_CLOSEST,可能返回一个同步或者不同步的帧,但是是在这个时间戳附近,并且对于系统性能的开销 比较大
    至此,这些关键的方法知道怎么用了,注意在加载完了之后,要释放fmmr对象,即fmmr.release()。

2、加载单个在线视频的略缩图

熟悉了上面的方法之后,现在就要写加载视频略缩图的方法了,代码如下:

public Bitmap getVideoThumbnail(String videoUrl){
	Bitmap generateBitmap = null;
	FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();
	try {
		fmmr.setDataSource(videoUrl);
		generateBitmap = fmmr.getFrameAtTime();
		if (generateBitmap != null) {
			Bitmap b2 = fmmr.getFrameAtTime(4000000,FFmpegMediaMetadataRetriever.OPTION_CLOS EST_SYNC);
			if (b2 != null) {
			//获取到了Bitmap之后用android自带的ThumbnailUtils获取自定义大小的略缩图
			generateBitmap = ThumbnailUtils.extractThumbnail(b2,
			640, 640,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
			}
		}
	} catch (IllegalArgumentException ex) {
		ex.printStackTrace();
	} finally {
		fmmr.release();
	}
	if(generateBitmap != null){
		return generateBitmap;
	}
	return null;
}

将这个方法封装到自己的工具类中就可以加载单个在线视频的略缩图了。

3、加载多个视频的略缩图

 

/**
* @author Chuck Chan
* @date 2014-10-28 下午4:48:56
* @param url 要加载资源的地址
* @param imageView 显示略缩图的ImageView控件
*/
public void loadVideoBitmap(String url, ImageView imageView) {
  //缓存中的Bitmap
  Bitmap bitmap = getBitmapFromCache(url);
  //缓存中不存在就从网络上获取资源
  if (bitmap == null) {
      forceDownload(url, imageView);
  } else {
      imageView.setVisibility(View.VISIBLE);
      cancelPotentialDownload(url, imageView);      
	  //imageView.setTag(bitmap);
      imageView.setImageBitmap(ThumbnailUtils.extractThumbnail(bitmap, 72,72));
  }
}
/**
* @author Chuck Chan
* @date 2014-10-28 下午4:53:49
* @param url 资源地址
* @param imageView 加载略缩图的ImageView控件
*/
private void forceDownload(String url, ImageView imageView) {
	// State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys.
	if (url == null) {
		imageView.setImageDrawable(null);
		return;
	}
	//判断是否需要下载
	if (cancelPotentialDownload(url, imageView)) {
		imageView.setVisibility(View.VISIBLE);
		BitmapWorkerTask task = new BitmapWorkerTask(imageView);
		Bitmap defaultBimap = BitmapFactory.decodeStream(mContext.getResources().openRawResource(R.drawable.user_icon_default));
		AsyncDrawable downloadedDrawable = new AsyncDrawable(mContext.getResources() , defaultBimap , task);
		imageView.setImageDrawable(downloadedDrawable);
		imageView.setMinimumHeight(72);
		task.execute(url);
	}
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
	private final WeakReference<ImageView> imageViewReference;
	private String url;
	public BitmapWorkerTask(ImageView imageView) {
		// Use a WeakReference to ensure the ImageView can be garbage collected
		imageViewReference = new WeakReference<ImageView>(imageView);
	}
	
	@Override
	protected Bitmap doInBackground(String... params) {
		url = params[0];
		//获取在线视频的帧的图像,返回Bitmap
		Bitmap tempBitmap = getVideoThumbnail(url);
		return tempBitmap;
	}
	
	@Override
	protected void onPostExecute(Bitmap bitmap) {
		if (isCancelled()) {
		bitmap = null;
		}
		addBitmapToCache(url, bitmap);
		if (imageViewReference != null && bitmap != null) {
			final ImageView imageView = imageViewReference.get();
			final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
			//判断当前的异步对象是否与ImageView所在的异步对象是否相等,以此来防止加载错乱
		if (this == bitmapWorkerTask && imageView != null) {             
			//             imageView.setTag(bitmap);
			imageView.setImageBitmap(ThumbnailUtils.extractThumbnail(bitmap, 72,72));
			}
		}
	}
}

将google博客中的方法结合自己修改的方法封装到工具类中,方便以后复用。