2014-02-03 2 views
8

Я пишу приложение для видеопроигрывателя с использованием API MediaCodec. Я должен показать пустой экран до начала декодирования видео. Поэтому я использую следующий код, чтобы показать пустой экран.native_window_api_connect возвратил ошибку: Неверный аргумент (-22)

Canvas c=null; 
      c = surfaceView.getHolder().lockCanvas(); 
      c.drawColor(Color.BLACK); 
      surfaceView.getHolder().unlockCanvasAndPost(c); 

После этого начнется декодирование видео. Но во время конфигурирования

videoDecoder.configure(format, surfaceView.getHolder().getSurface(), null, 0); 

она дает следующие ошибки

02-03 03:52:37.542: E/MediaCodec(9655): native_window_api_connect returned an error: Invalid argument (-22) 
02-03 03:52:37.542: E/Video Decoder Configuration(9655): java.lang.IllegalStateException 

Так что мои приложения аварии с этой ошибкой. Без этого пустой декодер кода экрана работает нормально. Как я могу решить эту проблему?

+0

Вы также видите сообщение журнала о «connect: already connected» в журнале? – fadden

+0

Привет, fadden, У меня нет такой строки в моем журнале. – saa

ответ

6

Вот моя теория, основанная на быстром просмотре кода рамки.

Операция блокировки холста (в конечном счете) вызывает в Surface::lock() (code here). То есть кусок кода, который говорит:

if (!mConnectedToCpu) { 
    int err = Surface::connect(NATIVE_WINDOW_API_CPU); 

Это подключение «производитель CPU», то есть код, который работает на процессоре и генерирует графические данные, на сторону производителя очереди буфера, который подает на поверхность , Этот производитель не отключен в unlockAndPost(). Вы действительно можете найти вызов разъединения в Surface destructor, который немного опоздал для ваших целей.

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

Я считаю, что у вас есть несколько вариантов:

  1. Blank поверхность с OpenGL ES. Когда вы уничтожите EGLSurface, он отключится. Для этого необходимо настроить EGL/GLES и получить код выхода EGL вправо.
  2. Поместите пустой прямоугольник, используя подход, отличный от чертежа на самом SurfaceView (h/t мой офис-помощник).

Для захода на посадку # 2, вам просто нужен второй вид (может быть, ImageView) с той же позиции и размеры как SurfaceView, и залейте его непрозрачным черным. Уровень SurfaceView всегда находится под всем остальным (при условии, что вы не настроили его на верх), поэтому элементы пользовательского интерфейса будут рисовать поверх него. Когда пришло время начать воспроизведение фильма, вы отключите другое представление.

Обновление: Теперь вы можете увидеть подход № 1 в Grafika. В действии «Воспроизвести фильм (SurfaceView)» он создает контекст EGL, очищает поверхность и разрушает контекст. (Необходимо немедленно уничтожить контекст и поверхность EGL, чтобы избежать проблемы «двух производителей».)

+1

Я получил ее на работу. Большое спасибо! Я написал фрагмент, чтобы сделать это, и оставил его здесь. Надеюсь, это поможет кому-то другому. https://gist.github.com/hisui/433e09e899175844cfc4 – findall

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