Android视频正逆序播放

本文介绍了如何在Android中实现视频逆序播放的功能。通过处理视频的YUV原始数据,从最后一帧开始逐帧向前播放,以达到逆序的效果。详细讲解了实现这一功能的思路和关键代码。
摘要由CSDN通过智能技术生成

前段时间拿到需求,需要在视频编辑模块中增加一个视频逆序播放的功能,就是从视频的最后一帧往前播放到第一帧。拿到需求时一脸懵逼,使用普通简洁的方式根本做不了,编码后的视频都是由I帧、P帧、B帧三种格式的帧组成的。思索良久后发现可以使用视频原始数据YUV数据来一帧帧绘制完成,废话不多说,直接上代码。

package com.yi.moments.capture;

import android.content.Intent;
import android.graphics.Bitmap;
import android.opengl.GLSurfaceView;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.yi.moments.constants.ConstKey;
import com.yi.moments.spore.ImageUtilEngine;
import com.yi.moments.spore.SporeRender;
import com.yi.moments.R;
import com.yi.moments.activity.BaseActivity;
import com.yi.moments.log.YiLog;
import com.yi.moments.util.ImageCompressUtil;
import com.yi.moments.util.ScreenUtil;
import com.yi.moments.util.ToastHelper;
import com.yi.moments.util.YUVUtils;
import com.yi.moments.view.VideoTimeSelectBar;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class VideoRecyclerPlayerActivity extends BaseActivity implements View.OnClickListener {

    private static final String TAG = "VideoRecyclerPlayerActivity";

    private static final int PICTURE_COUNT = 9;         //截取图片的数量
    private static final int VIDEO_PLAY_NORMAL = 0;     //正序
    private static final int VIDEO_PLAY_REVERSE = 1;    //逆序
    private static final int VIDEO_PLAY_RECYCLER = 2;   //循环

    private ImageView btnVideoPlayState;
    private GLSurfaceView mProcessView;
    private FrameLayout mProcessView_Layout;
    private LinearLayout recyclerBackgroundLayout;
    private VideoTimeSelectBar videoTimeSelectBar;

    private int width = 720;
    private int height = 1280;
    private int videoPlayOrder;
    private int sizePreFrame;
    private int playStartIndex;
    private int playEndIndex;
    private int frameRate = 15;
    private boolean isComposeVideo;
    private String sourceDataPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/yuvData.yuv";

    private SporeRender mRender;
    private ImageUtilEngine imageEngine;
    private RecyclerThread recyclerThread;
    private List<Bitmap> backgroundList = new ArrayList<>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_video_recycler_player);

        imageEngine = new ImageUtilEngine();

        btnVideoPlayState = findView(R.id.btnVideoPlayState);
        mProcessView_Layout = findView(R.id.process_view_layout);
        videoTimeSelectBar = findView(R.id.videoTimeSelectBar);
        recyclerBackgroundLayout = findView(R.id.recyclerBackgroundLayout);

        mProcessView = new GLSurfaceView(this);
        mProcessView_Layout.addView(mProcessView, 0);
        mRender = new SporeRender();
        mProcessView.setRenderer(mRender);

        btnVideoPlayState.setOnClickListener(this);
        findView(R.id.imgEditBack).setOnClickListener(this);
        findView(R.id.btnEditFinish).setOnClickListener(this);
        videoTimeSelectBar.setOnSelectTimeLiatener(new VideoTimeSelectBar.OnSelectTimeListener() {
            @Override
            public void onUpdate(int startIndex, int endIndex) {
                playStartIndex = startIndex;
                playEndIndex = endIndex;
                recyclerThread.setFrameIndex(playStartIndex);
            }
        });

        Intent intent = getIntent();
        width = intent.getIntExtra(ConstKey.KEY_YUV_DATA_WIDTH, width);
        height = intent.getIntExtra(ConstKey.KEY_YUV_DATA_HEIGHT, height);
        int mFrameRate = intent.getIntExtra(ConstKey.KEY_YUV_DATA_FRAME_RATE, frameRate);
        if(mFrameRate > 0){
            frameRate = mFrameRate;
        }
        String mSourceDataPath = intent.getStringExtra(ConstKey.KEY_YUV_DATA_PATH);
        if(!TextUtils.isEmpty(mSourceDataPath)){
            sourceDataPath = mSourceDataPath;
        }

        sizePreFrame = (int)(width * height * 1.5);
        PictureAsyncTask asyncTask = new PictureAsyncTask();
        asyncTask.execute(sourceDataPath);
    }

    private void showYUV(){
        recyclerThread = new RecyclerThread(sizePreFrame);
        recyclerThread.start();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(recyclerThread != null){
            recyclerThread.setSuspend(false);
        }else {
            showYUV();
        }
    }

    @Override
    protected void onPause() {
        super.onPause()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值