简体   繁体   中英

Getting ArrayIndexOutOfBoundsException when using JCodec in android

I am creating a video from the static images present in the external storage of my phone. The video will be like an automatic slideshow of the images. I have used JCodec for it.

Below is my code.

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface; 
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect; 
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment; 
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;

import java.io.File;
import java.io.IOException;

public class VideoActivity extends AppCompatActivity{

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    video();
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Video Created") //
            .setMessage("Hi this video is created") //
            .setPositiveButton("Play", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    // TODO
                    Log.d("dee","On Click on the play button");
                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ "/output97.mp4"));
                    intent.setDataAndType(Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+"/output97.mp4"), "video/mp4");
                    startActivity(intent);
                    dialog.dismiss();
                }
            }) //
            .setNegativeButton(("Share"), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_SEND);
                    Uri uri = Uri.fromFile(GetSDPathToFile("","output67.mp4"));
                    intent.putExtra(Intent.EXTRA_STREAM, uri);
                    intent.setDataAndType(uri, "video/*");
                    intent.setType("video/mp4");
                    startActivity(intent);
                    dialog.dismiss();
                }
            });
    builder.show();

}

public void video() {
    try {

        //Harsh bhaiya change the directory name in the GetSdToPath() Function in the belwo 1 lines
        File file = this.GetSDPathToFile("", "output97.mp4");
        NewSequenceEncoder encoder = new NewSequenceEncoder(file);
        File folder = new File(Environment.getExternalStorageDirectory() +"/numeros/fshhaq/") ;
        File[] listFile = folder.listFiles();
        // only 5 frames in total
        String text = "Numero";
        for (int i = 1; i <=  listFile.length; i++) {
            String _path=listFile[i-1].getAbsolutePath();
            Log.d("dee","pathhhhhhhhhhhh12"+_path);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            Bitmap bitmap = BitmapFactory.decodeFile(_path, options);
            Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
            //Log.d("dee","reached here");
            Log.d("dee","image " + i);
            Typeface tf = Typeface.create("Helvitica", Typeface.NORMAL);
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.WHITE);
            paint.setTypeface(tf);
            Log.d("dee","reached before the typface");
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setTextSize(convertToPixels(getApplicationContext(),16));
            Rect textRect = new Rect();
            Log.d("dee","created the rectange");
            paint.getTextBounds(text, 0, text.length(), textRect);
            //            Log.d("dee","reached here2");
            Canvas canvas = new Canvas(mutableBitmap);
            Log.d("dee","reached here3");

            //If the text is bigger than the canvas , reduce the font size
            if (textRect.width() >= (canvas.getWidth() - 4))     //the padding on either sides is considered as 4, so as to appropriately fit in the text
            {
                Log.d("dee", "Let us know");
                paint.setTextSize(convertToPixels(getApplicationContext(), 7));        //Scaling needs to be used for different dpi's
            }
            //Calculate the positions
            int xPos= (canvas.getWidth() -105);     //-2 is for regulating the x position offset
            Log.d("dee","reached the jesus");
            Log.d("dee",canvas.getWidth() + "");
            Log.d("dee",canvas.getWidth() + " sbjgbsdj "  + canvas.getHeight());
            //"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
            int yPos = (int) ((canvas.getHeight())-50);
            canvas.drawText("00O", xPos, yPos, paint);
            //int bitmapResId = this.getB.getIdentifier("image" + (i),"drawable", this.getPackageName());
            //Log.d("dee", this.getResources().getIdentifier("image" + (i),  "drawable", this.getPackageName()) + "  " +" is the no");
            Log.d("dee","image  "+i+"This is the required image number");
            //Log.d("dee",this.getBitmapFromResources(getApplicationContext().getResources(),bitmapResId).toString());
            // Bitmap bitmap = getBitmapFromResources(this.getResources(), bitmapResId);
            //Log.d("dee",R.drawable.class.getResource().l   +"  fields in drawable");
            //BitmapDrawable bitmap1 = this.writeTextOnDrawable(bitmapResId,"NUMERO",getApplicationContext());
            Picture pic = this.fromBitmap(mutableBitmap);
            //Toast.makeText(getApplicationContext(),"Image +" + i,Toast.LENGTH_SHORT).show();
            Log.d("dee",pic.getColor() +" "+pic.createCompatible());
            encoder.encodeNativeFrame(pic);
            Log.d("dee","reached here4");
        }
        Log.d("dee","reached here5");
       // int bitmapResId = this.getResources().getIdentifier("image6", "drawable", this.getPackageName());
        //Log.d("dee",this.getBitmapFromResources(getApplicationContext().getResources(),bitmapResId).toString());
        //Bitmap bitmapp = getBitmapFromResources(this.getResources(), bitmapResId);
        Log.d("dee","reached here6");
       // Picture pic = this.fromBitmap((bitmapp));
        //Log.d("dee",pic.getWidth() + "  " + pic.getHeight());
        Log.d("dee","reached here7");
        //encoder.encodeNativeFrame(pic);
        Log.d("dee","reached here9");
        encoder.finish();
        Log.d("dee","reached here8");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private Bitmap getBitmapFromResources(Resources resources, int bitmapResId) {
    return BitmapFactory.decodeResource(resources, bitmapResId);
}
//Change the path in the below function harsh bhaiya
protected File GetSDPathToFile(String filePatho, String fileName) {
    File extBaseDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    Log.d("dee",  Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES).toString());
    if (filePatho == null || filePatho.length() == 0 || filePatho.charAt(0) != '/')
        filePatho = "/" + filePatho;
    createDirIfNotExists(filePatho);
    File file = new File(extBaseDir.getAbsoluteFile() + filePatho);
    return new File(file.getAbsolutePath() + "/" + fileName);// file;
}


//cahnge in this one too
public static boolean createDirIfNotExists(String path) {
    boolean ret = true;
    File file = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), path);
    if (!file.exists()) {
        if (!file.mkdirs()) {
            Log.e("TravellerLog :: ", "Problem creating Image folder");
            ret = false;
        }
    }
    return ret;
}

public Picture fromBitmap(Bitmap src) {
    Picture dst = Picture.create(src.getWidth(), src.getHeight(), ColorSpace.RGB);
    fromBitmap(src, dst);
    Log.d("dee", dst.getWidth() + "");
    return dst;
}
public void fromBitmap(Bitmap src, Picture dst) {
    int[] dstData = dst.getPlaneData(0);
    int[] packed = new int[src.getWidth() * src.getHeight()*4];

    src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());

    for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
        for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
            int rgb = packed[srcOff];
            dstData[dstOff]     = (rgb >> 16) & 0xff;
            dstData[dstOff + 1] = (rgb >> 8) & 0xff;
            dstData[dstOff + 2] = rgb & 0xff;
        }
    }
}
public static int convertToPixels(Context context, int nDP)
{
    final float conversionScale = context.getResources().getDisplayMetrics().density;
    return (int) ((nDP * conversionScale) + 0.5f) ;
}

}

I am getting the ArrayIndexOutOfBoundsException error. Following is the logcat

Process: org.example.android.numero, PID: 8567 java.lang.RuntimeException: Unable to start activity ComponentInfo{org.example.android.numero/org.example.android.numero.VideoActivity}: java.lang.ArrayIndexOutOfBoundsException: length=589824; index=589824
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2365)
    at android.app.ActivityThread.access$800(ActivityThread.java:147)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5237)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=589824; index=589824
    at org.jcodec.scale.RgbToYuv420j.rgb2yuv(RgbToYuv420j.java:72)
    at org.jcodec.scale.RgbToYuv420j.transform(RgbToYuv420j.java:38)
    at org.example.android.numero.NewSequenceEncoder.encodeNativeFrame(NewSequenceEncoder.java:68)
    at org.example.android.numero.VideoActivity.video(VideoActivity.java:124)
    at org.example.android.numero.VideoActivity.onCreate(VideoActivity.java:36)
    at android.app.Activity.performCreate(Activity.java:5982)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2258)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2365) 
    at android.app.ActivityThread.access$800(ActivityThread.java:147) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5237) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)

Can anyone suggest me where i am going wrong? I feel there is some problem with the resolution of the picture.

Edit: I have overridden a method in JCodec ( sequenceEncoder ) to newSequenceEncoder , in order to control the frames per second on the video.

Because in below loop you are going equal to the length of the array but array starts from 0 and goes length-1

for(int i = 1; i <=  listFile.length; i++)

it suppose to be this

for(int i = 1; i <  listFile.length; i++)

plus you are missing the first file name by starting loop from 1 so it should be

for(int i = 0; i <  listFile.length; i++)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM