最近分析了幾個和omx播放相關的問題,從播放器的角度,對omx流程有了進一步的了解。
相關處理主要在:gst-omx-1.9.1/omx/gstomxvideodec.c
1 gst_omx_video_dec_handle_frame
gstreamer調用此函數,給omx decoder發送待解碼的packets。
主要處理流程如下:
2226 if (!self->started) { // 第一次進入 2232 gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self), 2233 (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL); // 啟動解碼線程 2234 } 2258 port = self->dec_in_port; // 獲取端口;因為這個端口是給omx解碼器送數據的,所以獲取的是in port。 2266 acq_ret = gst_omx_port_acquire_buffer (port, &buf); // 從端口中申請一個空閑buffer。 // enter: gst_omx_port_acquire_buffer 1353 _buf = g_queue_pop_head (&port->pending_buffers); // 從端口的鏈表中獲取bufferr // leave: gst_omx_port_acquire_buffer 2383 buf->omx_buf->nFilledLen = 2384 MIN (size - offset, buf->omx_buf->nAllocLen - buf->omx_buf->nOffset); // 計算實際傳送的數據長度 2385 gst_buffer_extract (frame->input_buffer, offset, 2386 buf->omx_buf->pBuffer + buf->omx_buf->nOffset, 2387 buf->omx_buf->nFilledLen); // 把Frame中的數據拷貝到omx port buffer。 2420 err = gst_omx_port_release_buffer (port, buf); // 把填充過數據的omx port buffer還給omx port。 // enter:gst_omx_port_release_buffer 1427 if (port->port_def.eDir == OMX_DirInput) { 1428 err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf); // omx 解碼器的接口函數:發送待解碼數據。解碼器處理完, // 會調用dec->callbacks.EmptyBufferDone通知omx插件。 1429 } else { 1430 err = OMX_FillThisBuffer (comp->handle, buf->omx_buf); 1431 } // leave:gst_omx_port_release_buffer
至此, gst_omx_video_dec_handle_frame發送packets完成。
2 gst_omx_video_dec_loop
把omx decoder解碼后的幀,發送給gstreamer播放器。
主要處理流程如下:
1263 port = self->dec_out_port; // 獲取端口;因為這個端口是用來獲取omx解碼后的數據的,所以獲取的是out port。 1266 acq_return = gst_omx_port_acquire_buffer (port, &buf); // 從端口中申請一個空閑buffer。 // enter: gst_omx_port_acquire_buffer 1353 _buf = g_queue_pop_head (&port->pending_buffers); // 從端口的鏈表中獲取bufferr // leave: gst_omx_port_acquire_buffer 1499 if ((flow_ret = 1500 gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER 1501 (self), frame)) == GST_FLOW_OK) { // 從gstreamer播放器申請buffer,用來存儲解碼后的數據 1506 if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) { // 把omx buffer的數據拷貝到gstreamer播放器的buffer 1513 } 1520 flow_ret = 1521 gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); // 把帶有解碼后數據的frame,傳送給后續插件 1525 } 1535 if (buf) { 1537 err = gst_omx_port_release_buffer (port, buf); // 把omx out port的buffer還回去 // enter:gst_omx_port_release_buffer 1427 if (port->port_def.eDir == OMX_DirInput) { 1428 err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf); 1429 } else { 1430 err = OMX_FillThisBuffer (comp->handle, buf->omx_buf); // omx 解碼器的接口函數:把空buffer還給omx,以便存放新的解碼后的數據。
// 解碼器解碼完,調用dec->callbacks.FillBufferDone通知omx插件 1431 } // leave:gst_omx_port_release_buffer 1540 }