gstreamer omx 解码器代码分析
最近分析了几个和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 }