【问题标题】:Error in retrieving multiple frames of a video via FFmpegMediaMetadataRetriever通过 FFmpegMediaMetadataRetriever 检索视频的多帧时出错
【发布时间】:2016-07-25 13:13:27
【问题描述】:

我正在尝试从视频中获取多个帧,但有时会出现致命异常。我在这里做的是,如果方向是纵向的,我会取帧一段时间并旋转。失败的原因可能是内存问题。请提出我错在哪里。

private ArrayList<Bitmap> getFrames() {

    ArrayList<Bitmap> bmFrames = new ArrayList<>();
    Bitmap bmp = null;
    Bitmap orientedBitmap = null;

    try {
        int baseTime = Integer.parseInt(model.getDuration());
        baseTime = baseTime / 11 * 1000;

        baseTimeArray = new int[11];
        for (int i = 0; i < 11; i++) {
            baseTimeArray[i] = baseTime * (i);

            Log.d("TAG", "fetching frame from " + baseTimeArray[i]);

            try {
                FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
                mmr.setDataSource(new File(sourceFilePath).getAbsolutePath());
                bmp = getBitmapViaFFMPEG(baseTimeArray[i], mmr);

                if (rotationMetaData != null) {
                    Matrix matrix = new Matrix();

                    matrix.postRotate(90);

                    //Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp,50,50,true);
                    if (bmp != null)
                        orientedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
                    else
                        Log.d(TAG,"returned bitmap was null");
                }
                //Log.d("TAG", "rotation: " + rotation);
                mmr.release();
            } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
            } catch (RuntimeException ex) {
                ex.printStackTrace();
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            if (rotationMetaData != null)
                bmFrames.add(orientedBitmap);
            else
                bmFrames.add(bmp);


        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bmFrames;
}

错误日志

【问题讨论】:

  • 嗨。你解决了你的问题吗?如果可以,请分享解决方案?
  • 我会在星期一分享解决方案。
  • 好的,谢谢! @拉利特
  • @HardikJoshi 对不起兄弟,我迟到了,但我回答了。
  • 没问题,兄弟。非常感谢(Y)

标签: android performance bitmap frames


【解决方案1】:

我知道发布答案为时已晚,但它仍然可以帮助某人。下面的类可用于显示视频帧

public class TimeLineView extends View {

private Uri mVideoUri;
private int mHeightView;
private LongSparseArray<Bitmap> mBitmapList = null;

public TimeLineView(@NonNull Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public TimeLineView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    mHeightView = getContext().getResources().getDimensionPixelOffset(R.dimen.frames_video_height);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int minW = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
    int w = resolveSizeAndState(minW, widthMeasureSpec, 1);

    final int minH = getPaddingBottom() + getPaddingTop() + mHeightView;
    int h = resolveSizeAndState(minH, heightMeasureSpec, 1);

    setMeasuredDimension(w, h);
}

@Override
protected void onSizeChanged(final int w, int h, final int oldW, int oldH) {
    super.onSizeChanged(w, h, oldW, oldH);

    if (w != oldW) {
        getBitmap(w);
    }
}

private void getBitmap(final int viewWidth) {
    BackgroundExecutor.execute(new BackgroundExecutor.Task("", 0L, "") {
                                   @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                                   @Override
                                   public void execute() {
                                       try {
                                           LongSparseArray<Bitmap> thumbnailList = new LongSparseArray<>();

                                           MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
                                           mediaMetadataRetriever.setDataSource(getContext(), mVideoUri);

                                           // Retrieve media data
                                           long videoLengthInMs = Integer.parseInt(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) * 1000;

                                           // Set thumbnail properties (Thumbs are squares)
                                           final int thumbWidth = mHeightView;
                                           final int thumbHeight = mHeightView;

                                           int numThumbs = (int) Math.ceil(((float) viewWidth) / thumbWidth);

                                           final long interval = videoLengthInMs / numThumbs;

                                           for (int i = 0; i < numThumbs; ++i) {
                                               Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(i * interval, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                                               // TODO: bitmap might be null here, hence throwing NullPointerException. You were right
                                               try {
                                                   bitmap = Bitmap.createScaledBitmap(bitmap, thumbWidth, thumbHeight, false);
                                               } catch (Exception e) {
                                                   e.printStackTrace();
                                               }
                                               thumbnailList.put(i, bitmap);
                                           }

                                           mediaMetadataRetriever.release();
                                           returnBitmaps(thumbnailList);
                                       } catch (final Throwable e) {
                                           Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                                       }
                                   }
                               }
    );
}

private void returnBitmaps(final LongSparseArray<Bitmap> thumbnailList) {
    UiThreadExecutor.runTask("", new Runnable() {
                @Override
                public void run() {
                    mBitmapList = thumbnailList;
                    invalidate();
                }
            }
            , 0L);
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onDraw(@NonNull Canvas canvas) {
    super.onDraw(canvas);

    if (mBitmapList != null) {
        canvas.save();
        int x = 0;

        for (int i = 0; i < mBitmapList.size(); i++) {
            Bitmap bitmap = mBitmapList.get(i);

            if (bitmap != null) {
                canvas.drawBitmap(bitmap, x, 0, null);
                x = x + bitmap.getWidth();
            }
        }
    }
}

public void setVideo(@NonNull Uri data) {
    mVideoUri = data;
}
}

并像这样使用

mTimeLineView = (TimeLineView) view.findViewById(R.id.timelineview);
mTimeLineView.setVideo(Uri.parse("video_path"));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-13
    • 2021-06-08
    • 2015-08-22
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    相关资源
    最近更新 更多