2012-08-26 2 views
4

У меня есть служба, и я пытаюсь сделать запись записи службы в файл.Неверная предварительная обработка видеоизображения в андроиде

Деятельность, которая запускает службу:

public static SurfaceView mSurfaceView; 
public static SurfaceHolder mSurfaceHolder; 
public static Camera mCamera; 
@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1); 
    mSurfaceHolder = mSurfaceView.getHolder(); 
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    mSurfaceHolder.addCallback(this); 
    Intent intent = new Intent(MainActivity.this, RecordService.class); 
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    startService(intent); 
    finish(); 
} 

служба:

private MediaRecorder mMediaRecorder; 
private SurfaceView mSurfaceView; 
private SurfaceHolder mSurfaceHolder; 
private boolean mRecordingStatus; 
private Camera mServiceCamera; 
private Size mPreviewSize; 

@Override 
public void onCreate() 
{ 
    mRecordingStatus = false; 
    mSurfaceView = MainActivity.mSurfaceView; 
    mSurfaceHolder = MainActivity.mSurfaceHolder; 
    mServiceCamera=MainActivity.mCamera; 
    InitCamera(); 
    super.onCreate(); 
} 
@Override 
public int onStartCommand(Intent intent, int flags, int startId) 
{ 
    super.onStartCommand(intent, flags, startId); 
    if (!mRecordingStatus) 
     StartRecord(); 
    else 
     StopRecord(); 

    return START_STICKY; 
} 
private void InitCamera() 
{ 
    mServiceCamera = Camera.open(); 
    Camera.Parameters p = mServiceCamera.getParameters(); 

    final List<Size> listSize = p.getSupportedPreviewSizes(); 
    mPreviewSize = listSize.get(2); 
    p.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
    p.setPreviewFormat(PixelFormat.YCbCr_420_SP); 
    mServiceCamera.setParameters(p); 
    try 
    { 
     mServiceCamera.setPreviewDisplay(mSurfaceHolder); 
     mServiceCamera.startPreview(); 
    } 
    catch (IOException e) 
    { 

     e.printStackTrace(); 
    } 

    mServiceCamera.unlock(); 
} 
private void StartRecord() 
{ 
    try 
    { 
     mMediaRecorder = new MediaRecorder(); 
     mMediaRecorder.setCamera(mServiceCamera); 
     mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
     mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
     mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 
     mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT); 
     mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory().getPath()+File.separator+ "video.mp4"); 
     mMediaRecorder.setVideoFrameRate(30); 
     mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height); 
     mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 

     mMediaRecorder.prepare(); 
     mMediaRecorder.start(); 

     mRecordingStatus = true; 

     Toast toast = Toast.makeText(getBaseContext(), "Recording",1000); 
     toast.show(); 
    } 
    catch (IOException e) 
    { 
     Toast toast = Toast.makeText(getBaseContext(), e.getMessage(),2000); 
     toast.show(); 
    } 
} 

когда я отлаживать код на мой Galaxy s я получаю тост (в методе StartRecord()) " недопустимая поверхность предварительного просмотра "

Как это можно исправить?

ответ

0

Я должен был запустить запуск MediaRecorder с некоторой задержкой. Это означает, что в onResume я создал обработчик и вызвал postDelayed. Я знаю, это все тот же раздел, но он работал со мной.

+0

Это работает, но кажется довольно взломанным. Лучше использовать обратные вызовы. См. Ответ от Sani – j7nn7k

12

Причина, по которой вы видели, - это то, что вы выполнили mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());, прежде чем поверхность была создана. Добавление задержки происходит, но это не правильный способ справиться с этим.

Линия mSurfaceHolder = mSurfaceView.getHolder(); не создает поверхность сразу. На самом деле SurfaceHolder предоставляет интерфейс обратного вызова, чтобы вы знали, когда поверхность была создана.

Строка mSurfaceHolder.addCallback(this); должна быть в конструкторе класса, который вы создаете, который расширяет SurfaceView и реализует SurfaceHolder.Callback. Затем вы можете переопределить методы обратного вызова интерфейса SurfaceHolder.Callback, чтобы ваш код выполнялся после того, как поверхность была создана. Вот пример:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 

private SurfaceHolder surfaceHolder; 


public CameraPreview(Context context, VideoHandler vh) { 
    super(context); 
    videoHandler = vh; 

    // Install a SurfaceHolder.Callback so we get notified when the 
    // underlying surface is created and destroyed. 
    surfaceHolder = getHolder(); 
    surfaceHolder.addCallback(this); 
    // deprecated setting, but required on Android versions prior to 3.0 
    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) 
     surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // Perform actions that require Surface to have been created here e.g. 
    // mMediaRecorder.setPreviewDisplay(holder.getSurface()); etc. 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    // Take care of releasing camera preview etc. 
} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    // Handle changes 
} 

} 
+0

Это должен быть принятый ответ. – CristianGuerrero

Смежные вопросы