Android MediaMetadataRetriever

通过MediaMetadataRetriever可以获取视频在对应时间的帧图像。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_retrieve_frames"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="获取前10秒的帧图像"/>

    <ListView
        android:id="@+id/lv_frames"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>


package com.example.media.codec;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;

import com.example.media.R;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;


public class MediaMetadataRetrieverActivity extends AppCompatActivity {
    private static final String TAG = MediaMetadataRetrieverActivity.class.getSimpleName();

    private FrameBitmapAdapter mFrameBitmapAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_media_metadata_retriever);

        ListView lvFrames = findViewById(R.id.lv_frames);
        List<Bitmap> framesBitmap = new ArrayList<>();
        mFrameBitmapAdapter = new FrameBitmapAdapter(this, framesBitmap);
        lvFrames.setAdapter(mFrameBitmapAdapter);

        findViewById(R.id.btn_retrieve_frames).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    Log.v(TAG, "external storage no exists");
                    return;
                }
                String videoDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() +
                        "/Android/data" + getPackageName() + "video/";
                File videoDir = new File(videoDirPath);
                if (!videoDir.exists()) {
                    if (!videoDir.mkdirs()) {
                        Log.v(TAG, "video dir create failed");
                        return;
                    }
                }
                String videoFilePath = videoDirPath + "test.mp4";

                new RetrieveFramesTask(MediaMetadataRetrieverActivity.this, videoFilePath).execute();
            }
        });
    }

    @SuppressLint("StaticFieldLeak")
    private class RetrieveFramesTask extends AsyncTask<Void, Void, List<Bitmap>> {
        private String mVideoFilePath;

        RetrieveFramesTask(Activity activity, String videoFilePath) {
            new WeakReference<>(activity);
            this.mVideoFilePath = videoFilePath;
        }

        @Override
        protected List<Bitmap> doInBackground(Void... voids) {
            List<Bitmap> frameBitmaps = new ArrayList<>();

            long timeUs = 1000;
            MediaMetadataRetriever mmr = new MediaMetadataRetriever();
            mmr.setDataSource(mVideoFilePath);
            while (timeUs <= 10 * 1000) {
                Bitmap frameBitmap = mmr.getFrameAtTime(timeUs);
                frameBitmaps.add(frameBitmap);
                timeUs += 1000;
            }

            return frameBitmaps;
        }

        @Override
        protected void onPostExecute(List<Bitmap> bitmaps) {
            super.onPostExecute(bitmaps);
            if (bitmaps != null && !bitmaps.isEmpty()) {
                mFrameBitmapAdapter.addAll(bitmaps);
                mFrameBitmapAdapter.notifyDataSetChanged();
            } else {
                Toast.makeText(MediaMetadataRetrieverActivity.this,
                        "frame bitmaps is null or empty", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private static class FrameBitmapAdapter extends BaseAdapter {
        private LayoutInflater mInflater;
        private List<Bitmap> mFrameBitmaps;

        FrameBitmapAdapter(Context context, List<Bitmap> frameBitmaps) {
            this.mInflater = LayoutInflater.from(context);
            this.mFrameBitmaps = frameBitmaps;
        }

        @Override
        public int getCount() {
            return mFrameBitmaps.size();
        }

        @Override
        public Bitmap getItem(int position) {
            return mFrameBitmaps.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            FrameBitmapViewHolder viewHolder;
            Bitmap frameBitmap = getItem(position);
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.frames_list_item, parent, false);
                viewHolder = new FrameBitmapViewHolder();
                viewHolder.ivFrameBitmap = convertView.findViewById(R.id.iv_frame_bitmap);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (FrameBitmapViewHolder) convertView.getTag();
            }

            viewHolder.ivFrameBitmap.setImageBitmap(frameBitmap);

            return convertView;
        }

        void addAll(@NonNull List<Bitmap> bitmaps) {
            mFrameBitmaps.addAll(bitmaps);
        }

        private static class FrameBitmapViewHolder {
            ImageView ivFrameBitmap;
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值