2016-07-25 102 views
0

我試圖從視頻中獲取多個幀,但它有時會產生致命異常。我在這裏做的是如果方向是縱向的,我正在抓取框架一段時間並旋轉。失敗的原因可能是記憶問題。請提出我錯在哪裏。通過FFmpegMediaMetadataRetriever檢索視頻的多幀時出錯

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; 
} 

錯誤日誌

enter image description here

+0

嗨。你解決了你的問題嗎?如果你能分享解決方案嗎? –

+0

我將在週一分享您的解決方案。 –

+0

好的,謝謝! @Lalit –

回答

0

我知道這是太晚發佈一個答案,但它仍然可以幫助別人。下面類可以用來顯示視頻幀

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"));