Beispiel #1
0
static void
omx_clk_init(omx_clk_t *clk, int has_audio)
{
  OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
  clk->has_audio = has_audio;
  clk->seek_in_progress = 0;
  OMX_INIT_STRUCTURE(cstate);
  cstate.eState = OMX_TIME_ClockStateStopped;
  omxchk(OMX_SetParameter(clk->c->oc_handle,
			  OMX_IndexConfigTimeClockState, &cstate));

  omx_set_state(clk->c, OMX_StateIdle);



  OMX_INIT_STRUCTURE(cstate);

  cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
  cstate.nWaitMask = has_audio ? 1 : 2;

  omxchk(OMX_SetParameter(clk->c->oc_handle,
			  OMX_IndexConfigTimeClockState, &cstate));

  OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
  OMX_INIT_STRUCTURE(refClock);
  refClock.eClock = has_audio ? OMX_TIME_RefClockAudio : OMX_TIME_RefClockVideo;

  omxchk(OMX_SetConfig(clk->c->oc_handle,
		       OMX_IndexConfigTimeActiveRefClock, &refClock));

  omx_set_state(clk->c, OMX_StateExecuting);

}
Beispiel #2
0
omx_tunnel_t *
omx_tunnel_create(omx_component_t *src, int srcport, omx_component_t *dst,
		  int dstport, const char *name)
{
  OMX_STATETYPE state;
  omxchk(OMX_GetState(src->oc_handle, &state));

  if(state == OMX_StateLoaded)
    omx_set_state(src, OMX_StateIdle);

  omxdbg("Creating tunnel %s from %s:%d to %s:%d\n",
	 name, src->oc_name, srcport, dst->oc_name, dstport);

  omx_send_command(src, OMX_CommandPortDisable, srcport, NULL, 1);
  omx_send_command(dst, OMX_CommandPortDisable, dstport, NULL, 1);
  omxchk(OMX_SetupTunnel(src->oc_handle, srcport, dst->oc_handle, dstport));
  omx_send_command(src, OMX_CommandPortEnable, srcport, NULL, 0);
  omx_send_command(dst, OMX_CommandPortEnable, dstport, NULL, 0);

  omxchk(OMX_GetState(dst->oc_handle, &state));
  if(state == OMX_StateLoaded)
    omx_set_state(dst, OMX_StateIdle);

  omx_tunnel_t *ot = malloc(sizeof(omx_tunnel_t));
  ot->ot_src = src;
  ot->ot_srcport = srcport;
  ot->ot_dst = dst;
  ot->ot_dstport = dstport;
  ot->ot_name = name;
  return ot;
}
Beispiel #3
0
static void
omx_mp_init(media_pipe_t *mp)
{
  if(!(mp->mp_flags & MP_VIDEO))
    return;

  omx_component_t *c;

  c = omx_component_create("OMX.broadcom.clock", &mp->mp_mutex, NULL);
  mp->mp_extra = c;

  omx_set_state(c, OMX_StateIdle);

  OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
  OMX_INIT_STRUCTURE(cstate);
  cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
  cstate.nWaitMask = 1;
  omxchk(OMX_SetParameter(c->oc_handle,
			  OMX_IndexConfigTimeClockState, &cstate));

  OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
  OMX_INIT_STRUCTURE(refClock);
  refClock.eClock = OMX_TIME_RefClockAudio;
  //  refClock.eClock = OMX_TIME_RefClockVideo;
  // refClock.eClock = OMX_TIME_RefClockNone;

  omxchk(OMX_SetConfig(c->oc_handle,
		       OMX_IndexConfigTimeActiveRefClock, &refClock));

  omx_set_state(c, OMX_StateExecuting);
}
Beispiel #4
0
void
omx_alloc_buffers(omx_component_t *oc, int port)
{
  OMX_PARAM_PORTDEFINITIONTYPE portdef;

  memset(&portdef, 0, sizeof(portdef));
  portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
  portdef.nVersion.nVersion = OMX_VERSION;
  portdef.nPortIndex = port;

  omxchk(OMX_GetParameter(oc->oc_handle, OMX_IndexParamPortDefinition, &portdef));
  if(portdef.bEnabled != OMX_FALSE || portdef.nBufferCountActual == 0 || portdef.nBufferSize == 0)
    exit(3);

  omxdbg("Allocating buffers for %s:%d\n", oc->oc_name, port);
  omxdbg("  buffer count = %d\n", (int)portdef.nBufferCountActual);
  omxdbg("  buffer size  = %d\n", (int)portdef.nBufferSize);

  omx_send_command(oc, OMX_CommandPortEnable, port, NULL, 0);
  int i;
  for(i = 0; i < portdef.nBufferCountActual; i++) {
    OMX_BUFFERHEADERTYPE *buf;
    omxchk(OMX_AllocateBuffer(oc->oc_handle, &buf, port, NULL, portdef.nBufferSize));
    omxdbg("buf=%p\n", buf);
    buf->pAppPrivate = oc->oc_avail;
    oc->oc_avail = buf;
    oc->oc_avail_bytes += buf->nAllocLen;
  }
  omx_wait_command(oc); // Waits for the OMX_CommandPortEnable command

}
Beispiel #5
0
static void
omx_mp_init(media_pipe_t *mp)
{
  if(!(mp->mp_flags & MP_VIDEO))
    return;

#if 0
  if(0) {
    mp->mp_seek_initiate = omx_mp_begin_seek;
    mp->mp_seek_audio_done = omx_mp_seek_audio_done;
    mp->mp_seek_video_done = omx_mp_seek_video_done;
  }
#endif

  mp->mp_hold_changed = omx_mp_hold_changed;


  omx_clk_t *clk = calloc(1, sizeof(omx_clk_t));
  TAILQ_INIT(&clk->q);
  clk->mp = mp;
  clk->c = omx_component_create("OMX.broadcom.clock", &mp->mp_mutex, NULL);
  hts_cond_init(&clk->cond, &mp->mp_mutex);
  mp->mp_extra = clk;

  omx_set_state(clk->c, OMX_StateIdle);
#if 0
  OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
  OMX_INIT_STRUCTURE(cstate);
  cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
  cstate.nWaitMask = 1;
  omxchk(OMX_SetParameter(c->oc_handle,
			  OMX_IndexConfigTimeClockState, &cstate));

  OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
  OMX_INIT_STRUCTURE(refClock);
  refClock.eClock = OMX_TIME_RefClockAudio;
  //  refClock.eClock = OMX_TIME_RefClockVideo;
  // refClock.eClock = OMX_TIME_RefClockNone;
#else
  OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
  OMX_INIT_STRUCTURE(cstate);
  cstate.eState = OMX_TIME_ClockStateRunning;
  omxchk(OMX_SetParameter(clk->c->oc_handle,
			  OMX_IndexConfigTimeClockState, &cstate));

  OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
  OMX_INIT_STRUCTURE(refClock);
  refClock.eClock = OMX_TIME_RefClockAudio;
#endif

  omxchk(OMX_SetConfig(clk->c->oc_handle,
		       OMX_IndexConfigTimeActiveRefClock, &refClock));

  omx_set_state(clk->c, OMX_StateExecuting);

  hts_thread_create_joinable("omxclkctrl", &clk->tid, omx_clk_thread, clk,
			     THREAD_PRIO_DEMUXER);
}
Beispiel #6
0
omx_component_t *
omx_component_create(const char *name, hts_mutex_t *mtx,
                     hts_cond_t *avail_cond)
{
  omx_component_t *oc = calloc(1, sizeof(omx_component_t));
  OMX_CALLBACKTYPE cb;
  const OMX_INDEXTYPE types[] = {OMX_IndexParamAudioInit,
                                 OMX_IndexParamVideoInit,
                                 OMX_IndexParamImageInit,
                                 OMX_IndexParamOtherInit};

  assert(mtx != NULL);
  oc->oc_mtx = mtx;

  oc->oc_avail_cond = avail_cond;

  hts_cond_init(&oc->oc_event_cond, oc->oc_mtx);

  oc->oc_name = strdup(name);

  cb.EventHandler    = oc_event_handler;
  cb.EmptyBufferDone = oc_empty_buffer_done;
  cb.FillBufferDone  = oc_fill_buffer_done;

  //  omxdbg("Creating %s\n", oc->oc_name);
  omxchk(OMX_GetHandle(&oc->oc_handle, oc->oc_name, oc, &cb));

  // Initially disable ports
  int i;
  for(i = 0; i < 4; i++) {
    OMX_PORT_PARAM_TYPE ports;
    ports.nSize = sizeof(OMX_PORT_PARAM_TYPE);
    ports.nVersion.nVersion = OMX_VERSION;

    omxchk(OMX_GetParameter(oc->oc_handle, types[i], &ports));
    omxdbg("%s: type:%d: ports: %d +%d\n", name, i, ports.nStartPortNumber, ports.nPorts);

    if(ports.nPorts > 0) {
      oc->oc_inport = ports.nStartPortNumber;
      oc->oc_outport = ports.nStartPortNumber + 1;
    }

    for(int j = 0; j < ports.nPorts; j++)
      omx_send_command(oc, OMX_CommandPortDisable, ports.nStartPortNumber + j, NULL, 1);

  }


  return oc;
}
Beispiel #7
0
void
omx_set_state(omx_component_t *oc, OMX_STATETYPE reqstate)
{
  OMX_STATETYPE state;
  int attempts = 20;
  omxchk(OMX_GetState(oc->oc_handle, &state));
  omxdbg("Telling component '%s' to go from state %d -> to state %d\n", oc->oc_name, state, reqstate);


  while(1) {
    oc->oc_cmd_done = 0;

    int r = OMX_SendCommand(oc->oc_handle, OMX_CommandStateSet,
                          reqstate, NULL);

    if(r == OMX_ErrorInsufficientResources && attempts) {
      usleep(10000);
      attempts--;
      continue;
    }

    if(r != 0) {
      panic("OMX Setstate %s from %d to %d error 0x%x",
            oc->oc_name, state, reqstate, r);
    }

    if(reqstate == OMX_StateExecuting)
      omx_wait_command(oc);

    return;
  }
}
Beispiel #8
0
static int64_t
rvd_newframe(glw_video_t *gv, video_decoder_t *vd, int flags)
{
  rpi_video_display_t *rvd = gv->gv_aux;

  if(rvd->rvd_vsched && rvd->rvd_reconfigure) {
    rvd->rvd_reconfigure = 0;

    if(rvd->rvd_tun_vsched_vrender)
      omx_tunnel_destroy(rvd->rvd_tun_vsched_vrender);
    
    rvd->rvd_tun_vsched_vrender =
      omx_tunnel_create(rvd->rvd_vsched, 11, rvd->rvd_vrender, 90,
			"vsched -> vrender");

    omx_set_state(rvd->rvd_vrender, OMX_StateExecuting);


    OMX_CONFIG_DISPLAYREGIONTYPE dr;
    OMX_INIT_STRUCTURE(dr);
    dr.nPortIndex = 90;
    dr.set = OMX_DISPLAY_SET_LAYER;
    dr.layer = 3;
    omxchk(OMX_SetConfig(rvd->rvd_vrender->oc_handle,
			 OMX_IndexConfigDisplayRegion, &dr));
  }
  return rvd->rvd_pts;
}
Beispiel #9
0
static rpi_pixmap_decoder_t *
pixmap_decoder_create(int cfmt)
{
  rpi_pixmap_decoder_t *rpd = calloc(1, sizeof(rpi_pixmap_decoder_t));
  hts_mutex_init(&rpd->rpd_mtx);
  hts_cond_init(&rpd->rpd_cond, &rpd->rpd_mtx);

  rpd->rpd_decoder = omx_component_create("OMX.broadcom.image_decode",
					  &rpd->rpd_mtx, &rpd->rpd_cond);

  rpd->rpd_decoder->oc_port_settings_changed_cb = decoder_port_settings_changed;
  rpd->rpd_decoder->oc_opaque = rpd;

  rpd->rpd_resizer = omx_component_create("OMX.broadcom.resize",
					  &rpd->rpd_mtx, &rpd->rpd_cond);

  omx_set_state(rpd->rpd_decoder, OMX_StateIdle);

  OMX_IMAGE_PARAM_PORTFORMATTYPE fmt;
  OMX_INIT_STRUCTURE(fmt);
  fmt.nPortIndex = rpd->rpd_decoder->oc_inport;
  fmt.eCompressionFormat = cfmt;
  omxchk(OMX_SetParameter(rpd->rpd_decoder->oc_handle,
			  OMX_IndexParamImagePortFormat, &fmt));

#ifndef NOCOPY
  omx_alloc_buffers(rpd->rpd_decoder, rpd->rpd_decoder->oc_inport);
  omx_set_state(rpd->rpd_decoder, OMX_StateExecuting);
#endif
  return rpd;
}
Beispiel #10
0
static void
rvd_render(glw_video_t *gv, glw_rctx_t *rc)
{
  rpi_video_display_t *rvd = gv->gv_aux;
  if(!memcmp(&rvd->rvd_pos, &gv->gv_rect, sizeof(glw_rect_t)))
    return;

  rvd->rvd_pos = gv->gv_rect;

  OMX_CONFIG_DISPLAYREGIONTYPE conf;
  OMX_INIT_STRUCTURE(conf);
  conf.nPortIndex = 90;

  conf.fullscreen = OMX_FALSE;
  conf.noaspect   = OMX_TRUE;

  conf.set =
    OMX_DISPLAY_SET_DEST_RECT |
    OMX_DISPLAY_SET_FULLSCREEN |
    OMX_DISPLAY_SET_NOASPECT;

  conf.dest_rect.x_offset = rvd->rvd_pos.x1;
  conf.dest_rect.y_offset = rvd->rvd_pos.y1;
  conf.dest_rect.width    = rvd->rvd_pos.x2 - rvd->rvd_pos.x1;
  conf.dest_rect.height   = rvd->rvd_pos.y2 - rvd->rvd_pos.y1;

  omxchk(OMX_SetConfig(rvd->rvd_vrender->oc_handle,
		       OMX_IndexConfigDisplayRegion, &conf));
}
Beispiel #11
0
static void
rpi_codec_decode(struct media_codec *mc, struct video_decoder *vd,
		 struct media_queue *mq, struct media_buf *mb, int reqsize)
{
  media_pipe_t *mp = vd->vd_mp;
  rpi_video_codec_t *rvc = mc->opaque;
  const void *data = mb->mb_data;
  size_t len       = mb->mb_size;

  while(len > 0) {
    OMX_BUFFERHEADERTYPE *buf = omx_get_buffer(rvc->rvc_decoder);
    buf->nOffset = 0;
    buf->nFilledLen = MIN(len, buf->nAllocLen);
    memcpy(buf->pBuffer, data, buf->nFilledLen);
    buf->nFlags = 0;


    if(rvc->rvc_last_epoch != mb->mb_epoch) {
      buf->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY;
      rvc->rvc_last_epoch = mb->mb_epoch;
    }

    if(len <= buf->nAllocLen)
      buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;

    data += buf->nFilledLen;
    len  -= buf->nFilledLen;

    if(mb->mb_pts != PTS_UNSET)
      buf->nTimeStamp = omx_ticks_from_s64(mb->mb_pts);
    else {
      buf->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
      buf->nTimeStamp = omx_ticks_from_s64(0);
    }

    if(mb->mb_skip)
      buf->nFlags |= OMX_BUFFERFLAG_DECODEONLY;

    if(rvc->rvc_decoder->oc_port_settings_changed) {
      rvc->rvc_decoder->oc_port_settings_changed = 0;
      frame_info_t fi;
      memset(&fi, 0, sizeof(fi));
      fi.fi_type        = 'omx';
      fi.fi_data[0]     = (void *)rvc->rvc_decoder;
      mp->mp_video_frame_deliver(&fi, mp->mp_video_frame_opaque);
    }

    omxchk(OMX_EmptyThisBuffer(rvc->rvc_decoder->oc_handle, buf));
  }  

  frame_info_t fi;
  memset(&fi, 0, sizeof(fi));
  fi.fi_drive_clock = mb->mb_drive_clock;
  fi.fi_epoch       = mb->mb_epoch;
  fi.fi_pts         = PTS_UNSET;
  fi.fi_delta       = mb->mb_delta;
  fi.fi_type        = 'omx';
  mp->mp_video_frame_deliver(&fi, mp->mp_video_frame_opaque);
}
Beispiel #12
0
void
omx_enable_buffer_marks(omx_component_t *oc)
{
  OMX_CONFIG_BOOLEANTYPE t;
  OMX_INIT_STRUCTURE(t);
  t.bEnabled = 1;
  omxchk(OMX_SetParameter(oc->oc_handle, OMX_IndexParamPassBufferMarks, &t));
}
Beispiel #13
0
void
omx_tunnel_destroy(omx_tunnel_t *ot)
{
  omxdbg("Destroying tunnel\n");
  omx_send_command(ot->ot_src, OMX_CommandPortDisable, ot->ot_srcport, NULL, 0);
  omx_send_command(ot->ot_dst, OMX_CommandPortDisable, ot->ot_dstport, NULL, 0);
  omxchk(OMX_SetupTunnel(ot->ot_src->oc_handle, ot->ot_srcport, NULL, 0));
  free(ot);
}
Beispiel #14
0
void
omx_set_state(omx_component_t *oc, OMX_STATETYPE reqstate)
{
  OMX_STATETYPE state;

  omxchk(OMX_GetState(oc->oc_handle, &state));
  omxdbg("Telling component '%s' to go from state %d -> to state %d\n", oc->oc_name, state, reqstate);
  omx_send_command(oc, OMX_CommandStateSet, reqstate, NULL, reqstate != OMX_StateLoaded);
}
Beispiel #15
0
void
omx_component_destroy(omx_component_t *oc)
{
  omxchk(OMX_FreeHandle(oc->oc_handle));

  free(oc->oc_name);
  hts_cond_destroy(&oc->oc_event_cond);
  free(oc);
}
Beispiel #16
0
static void
omx_clk_begin_seek(omx_clk_t *clk)
{
  omx_component_t *c = clk->c;

  OMX_TIME_CONFIG_CLOCKSTATETYPE cs;
  OMX_INIT_STRUCTURE(cs);
  cs.eState = OMX_TIME_ClockStateStopped;
  omxchk(OMX_SetParameter(c->oc_handle, OMX_IndexConfigTimeClockState, &cs));
  clk->seek_in_progress = 2;
}
Beispiel #17
0
static void
omx_mp_begin_seek(media_pipe_t *mp)
{
  omx_component_t *c = mp->mp_extra;

  OMX_TIME_CONFIG_CLOCKSTATETYPE cs;
  OMX_INIT_STRUCTURE(cs);
  cs.eState = OMX_TIME_ClockStateStopped;
  omxchk(OMX_SetParameter(c->oc_handle, OMX_IndexConfigTimeClockState, &cs));
  cnt = 2;
}
Beispiel #18
0
static void
omx_clk_set_speed(omx_clk_t *clk, int v)
{
  omx_component_t *c = clk->c;

  OMX_TIME_CONFIG_SCALETYPE scale;
  OMX_INIT_STRUCTURE(scale);

  scale.xScale = v;
  omxchk(OMX_SetConfig(c->oc_handle, OMX_IndexConfigTimeScale, &scale));
}
Beispiel #19
0
int64_t
omx_get_media_time(omx_component_t *oc)
{
  OMX_TIME_CONFIG_TIMESTAMPTYPE ts;
  OMX_INIT_STRUCTURE(ts);

  omxchk(OMX_GetConfig(oc->oc_handle,
		       OMX_IndexConfigTimeCurrentMediaTime,
		       &ts));
  return omx_ticks_to_s64(ts.nTimestamp);
 
}
Beispiel #20
0
void
omx_send_command(omx_component_t *oc, OMX_COMMANDTYPE cmd, int v, void *p,
		 int wait)
{
  oc->oc_cmd_done = 0;

  omxdbg("%s: CMD(0x%x, 0x%x, %p)\n", oc->oc_name, cmd, v, p);

  omxchk(OMX_SendCommand(oc->oc_handle, cmd, v, p));

  if(wait)
    omx_wait_command(oc);
}
Beispiel #21
0
static void
omx_mp_seek_audio_done(media_pipe_t *mp)
{
  cnt--;

  if(cnt == 0) {
    omx_component_t *c = mp->mp_extra;

    OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
    OMX_INIT_STRUCTURE(cstate);
    cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
    cstate.nWaitMask = 1;
    omxchk(OMX_SetParameter(c->oc_handle, OMX_IndexConfigTimeClockState, &cstate));
  }

}
Beispiel #22
0
static void
omx_clk_seek_done(omx_clk_t *clk)
{
  if(clk->seek_in_progress == 0)
    return;

  clk->seek_in_progress--;
  if(clk->seek_in_progress)
    return;

  omx_component_t *c = clk->c;

  OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
  OMX_INIT_STRUCTURE(cstate);
  cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
  cstate.nWaitMask = clk->has_audio ? 1 : 2;
  omxchk(OMX_SetParameter(c->oc_handle, OMX_IndexConfigTimeClockState, &cstate));
}
Beispiel #23
0
static void
setup_tunnel(rpi_pixmap_decoder_t *rpd)
{
  int dst_width, dst_height;
  OMX_PARAM_PORTDEFINITIONTYPE portdef;

  if(rpd->rpd_tunnel != NULL)
    return;

  OMX_INIT_STRUCTURE(portdef);
  portdef.nPortIndex = rpd->rpd_decoder->oc_outport;
  omxchk(OMX_GetParameter(rpd->rpd_decoder->oc_handle,
			  OMX_IndexParamPortDefinition, &portdef));

  pixmap_compute_rescale_dim(rpd->rpd_im,
			     portdef.format.image.nFrameWidth,
			     portdef.format.image.nFrameHeight,
			     &dst_width, &dst_height);

  portdef.nPortIndex = rpd->rpd_resizer->oc_inport;
  omxchk(OMX_SetParameter(rpd->rpd_resizer->oc_handle,
			  OMX_IndexParamPortDefinition, &portdef));

  rpd->rpd_tunnel = omx_tunnel_create(rpd->rpd_decoder,
				      rpd->rpd_decoder->oc_outport,
				      rpd->rpd_resizer,
				      rpd->rpd_resizer->oc_inport,
				      "decoder -> resizer");
  OMX_INIT_STRUCTURE(portdef);

  portdef.nPortIndex = rpd->rpd_resizer->oc_outport;
  omxchk(OMX_GetParameter(rpd->rpd_resizer->oc_handle,
			  OMX_IndexParamPortDefinition, &portdef));

  int stride = (dst_width * 4 + PIXMAP_ROW_ALIGN - 1) & ~(PIXMAP_ROW_ALIGN - 1);

  portdef.format.image.eCompressionFormat    = OMX_IMAGE_CodingUnused;
  portdef.format.image.eColorFormat          = OMX_COLOR_Format32bitABGR8888;
  portdef.format.image.nFrameWidth           = dst_width;
  portdef.format.image.nFrameHeight          = dst_height;
  portdef.format.image.nStride               = stride;
  portdef.format.image.nSliceHeight          = 0;
  portdef.format.image.bFlagErrorConcealment = OMX_FALSE;

  omxchk(OMX_SetParameter(rpd->rpd_resizer->oc_handle,
			  OMX_IndexParamPortDefinition, &portdef));

  omxchk(OMX_GetParameter(rpd->rpd_resizer->oc_handle,
			  OMX_IndexParamPortDefinition, &portdef));

  omx_set_state(rpd->rpd_resizer, OMX_StateExecuting);
  omx_port_enable(rpd->rpd_resizer, rpd->rpd_resizer->oc_outport);

  pixmap_t *pm = rpd->rpd_pm = calloc(1, sizeof(pixmap_t));
  pm->pm_refcount = 1;
  pm->pm_width    = portdef.format.image.nFrameWidth;
  pm->pm_height   = portdef.format.image.nFrameHeight;
  pm->pm_linesize = portdef.format.image.nStride;
  pm->pm_type     = PIXMAP_BGR32;
  pm->pm_data     = mymemalign(portdef.nBufferAlignment, portdef.nBufferSize);
  pm->pm_aspect   = (float)pm->pm_width / (float)pm->pm_height;

  omxchk(OMX_UseBuffer(rpd->rpd_resizer->oc_handle, &rpd->rpd_buf,
		       rpd->rpd_resizer->oc_outport,
		       NULL, portdef.nBufferSize, pm->pm_data));

  omx_wait_command(rpd->rpd_resizer);
  omxchk(OMX_FillThisBuffer(rpd->rpd_resizer->oc_handle, rpd->rpd_buf));
}
Beispiel #24
0
static int
rpi_codec_create(media_codec_t *mc, const media_codec_params_t *mcp,
		 media_pipe_t *mp)
{
  int fmt;

  switch(mc->codec_id) {

  case CODEC_ID_H264:
    fmt = OMX_VIDEO_CodingAVC;
    break;

  case CODEC_ID_MPEG2VIDEO:
    if(!omx_enable_mpg2)
      return 1;
    fmt = OMX_VIDEO_CodingMPEG2;
    break;

#if 0
  case CODEC_ID_VC1:
  case CODEC_ID_WMV3:
    if(mcp->extradata_size == 0)
      return 1;

    mc->decode = vc1_pt_decode;
    return 0;
#endif

  default:
    return 1;
  }

  rpi_video_codec_t *rvc = calloc(1, sizeof(rpi_video_codec_t));

  hts_cond_init(&rvc->rvc_avail_cond, &mp->mp_mutex);

  omx_component_t *d = omx_component_create("OMX.broadcom.video_decode",
					    &mp->mp_mutex,
					    &rvc->rvc_avail_cond);

  if(d == NULL) {
    hts_cond_destroy(&rvc->rvc_avail_cond);
    free(rvc);
    return 1;
  }

  rvc->rvc_decoder = d;

  omx_set_state(d, OMX_StateIdle);

  OMX_VIDEO_PARAM_PORTFORMATTYPE format;
  OMX_INIT_STRUCTURE(format);
  format.nPortIndex = 130; 
  format.eCompressionFormat = fmt;
  omxchk(OMX_SetParameter(d->oc_handle,
			  OMX_IndexParamVideoPortFormat, &format));

  OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE ec;
  OMX_INIT_STRUCTURE(ec);
  ec.bStartWithValidFrame = OMX_FALSE;
  omxchk(OMX_SetParameter(d->oc_handle,
			  OMX_IndexParamBrcmVideoDecodeErrorConcealment, &ec));

  
  OMX_CONFIG_BOOLEANTYPE bt;
  OMX_INIT_STRUCTURE(bt);
  bt.bEnabled = 1;
  omxchk(OMX_SetConfig(d->oc_handle,
		       OMX_IndexParamBrcmInterpolateMissingTimestamps, &bt));
  
  omx_alloc_buffers(d, 130);
  omx_set_state(d, OMX_StateExecuting);

  if(mcp->extradata_size) {

    hts_mutex_lock(&mp->mp_mutex);
    OMX_BUFFERHEADERTYPE *buf = omx_get_buffer_locked(rvc->rvc_decoder);
    hts_mutex_unlock(&mp->mp_mutex);
    buf->nOffset = 0;
    buf->nFilledLen = mcp->extradata_size;
    memcpy(buf->pBuffer, mcp->extradata, buf->nFilledLen);
    buf->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
    omxchk(OMX_EmptyThisBuffer(rvc->rvc_decoder->oc_handle, buf));
  }

  mc->opaque = rvc;
  mc->close  = rpi_codec_close;
  mc->decode = rpi_codec_decode;
  mc->flush  = rpi_codec_flush;
  return 0;
}
Beispiel #25
0
static pixmap_t *
rpi_pixmap_decode(pixmap_t *pm, const image_meta_t *im,
		  char *errbuf, size_t errlen)
{

  if(pm->pm_type != PIXMAP_JPEG)
    return NULL;

#ifdef TIMING
  int64_t ts = showtime_get_ts(), ts2;
#endif
  rpi_pixmap_decoder_t *rpd = pixmap_decoder_create(OMX_IMAGE_CodingJPEG);

  if(rpd == NULL)
    return NULL;
  rpd->rpd_im = im;

#ifdef NOCOPY


#error check rpd->rpd_decoder->oc_stream_corrupt

  OMX_PARAM_PORTDEFINITIONTYPE portdef;

  memset(&portdef, 0, sizeof(portdef));
  portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
  portdef.nVersion.nVersion = OMX_VERSION;
  portdef.nPortIndex = rpd->rpd_decoder->oc_inport;

  omxchk(OMX_GetParameter(rpd->rpd_decoder->oc_handle,
			  OMX_IndexParamPortDefinition, &portdef));

  omx_send_command(rpd->rpd_decoder, OMX_CommandPortEnable,
		   rpd->rpd_decoder->oc_inport, NULL, 0);

  OMX_BUFFERHEADERTYPE *buf;
  
  for(int i = 0; i < portdef.nBufferCountActual; i++) {
    omxchk(OMX_UseBuffer(rpd->rpd_decoder->oc_handle, &buf,
			 rpd->rpd_decoder->oc_inport, 
			 NULL, pm->pm_size, pm->pm_data));
  }

  // Waits for the OMX_CommandPortEnable command
  omx_wait_command(rpd->rpd_decoder);
  
  omx_set_state(rpd->rpd_decoder, OMX_StateExecuting);

  CHECKPOINT("Initialized");

  buf->nOffset = 0;
  buf->nFilledLen = pm->pm_size;

  buf->nFlags |= OMX_BUFFERFLAG_EOS;

  rpd->rpd_decoder->oc_inflight_buffers++;

  omxchk(OMX_EmptyThisBuffer(rpd->rpd_decoder->oc_handle, buf));
  
  hts_mutex_lock(&rpd->rpd_mtx);
  while(rpd->rpd_change == 0)
    hts_cond_wait(&rpd->rpd_cond, &rpd->rpd_mtx);
  hts_mutex_unlock(&rpd->rpd_mtx);
  CHECKPOINT("Setup tunnel");
  setup_tunnel(rpd);



#else

  const void *data = pm->pm_data;
  size_t len = pm->pm_size;



  hts_mutex_lock(&rpd->rpd_mtx);

  while(len > 0) {
    OMX_BUFFERHEADERTYPE *buf;

    if(rpd->rpd_decoder->oc_stream_corrupt)
      break;

    if(rpd->rpd_change == 1) {
      rpd->rpd_change = 2;
      hts_mutex_unlock(&rpd->rpd_mtx);
      setup_tunnel(rpd);
      hts_mutex_lock(&rpd->rpd_mtx);
      continue;
    }

    if(rpd->rpd_decoder->oc_avail == NULL) {
      hts_cond_wait(&rpd->rpd_cond, &rpd->rpd_mtx);
      continue;
    }

    buf = rpd->rpd_decoder->oc_avail;
    rpd->rpd_decoder->oc_avail = buf->pAppPrivate;
    rpd->rpd_decoder->oc_inflight_buffers++;

    hts_mutex_unlock(&rpd->rpd_mtx);

    buf->nOffset = 0;
    buf->nFilledLen = MIN(len, buf->nAllocLen);
    memcpy(buf->pBuffer, data, buf->nFilledLen);
    buf->nFlags = 0;

    if(len <= buf->nAllocLen)
      buf->nFlags |= OMX_BUFFERFLAG_EOS;

    data += buf->nFilledLen;
    len  -= buf->nFilledLen;
    omxchk(OMX_EmptyThisBuffer(rpd->rpd_decoder->oc_handle, buf));

    hts_mutex_lock(&rpd->rpd_mtx);
  }

  if(rpd->rpd_decoder->oc_stream_corrupt) {
    hts_mutex_unlock(&rpd->rpd_mtx);
    goto err;
  }

  if(rpd->rpd_change != 2) {
    while(rpd->rpd_change == 0 && !rpd->rpd_decoder->oc_stream_corrupt)
      hts_cond_wait(&rpd->rpd_cond, &rpd->rpd_mtx);

    

    hts_mutex_unlock(&rpd->rpd_mtx);
    if(rpd->rpd_decoder->oc_stream_corrupt)
      goto err;

    setup_tunnel(rpd);
  } else {
    hts_mutex_unlock(&rpd->rpd_mtx);
  }
#endif

  
  omx_wait_fill_buffer(rpd->rpd_resizer, rpd->rpd_buf);
  CHECKPOINT("Got buffer");

 err:
  omx_flush_port(rpd->rpd_decoder, rpd->rpd_decoder->oc_inport);
  omx_flush_port(rpd->rpd_decoder, rpd->rpd_decoder->oc_outport);

  omx_flush_port(rpd->rpd_resizer, rpd->rpd_resizer->oc_inport);
  omx_flush_port(rpd->rpd_resizer, rpd->rpd_resizer->oc_outport);



  if(rpd->rpd_tunnel != NULL) {
    omx_tunnel_destroy(rpd->rpd_tunnel);
    rpd->rpd_tunnel = NULL;
  }

  omx_set_state(rpd->rpd_decoder, OMX_StateIdle);
  omx_set_state(rpd->rpd_resizer, OMX_StateIdle);

  if(rpd->rpd_buf != NULL) {
    omxchk(OMX_FreeBuffer(rpd->rpd_resizer->oc_handle,
			  rpd->rpd_resizer->oc_outport, rpd->rpd_buf));
  }

  omx_release_buffers(rpd->rpd_decoder, rpd->rpd_decoder->oc_inport);

  omx_set_state(rpd->rpd_resizer, OMX_StateLoaded);
  omx_set_state(rpd->rpd_decoder, OMX_StateLoaded);

  omx_component_destroy(rpd->rpd_resizer);
  omx_component_destroy(rpd->rpd_decoder);
  hts_cond_destroy(&rpd->rpd_cond);
  hts_mutex_destroy(&rpd->rpd_mtx);

  pixmap_t *out = rpd->rpd_pm;
  if(out) {
    pixmap_release(pm);
  } else {
    snprintf(errbuf, errlen, "Load error");
  }

  free(rpd);
  CHECKPOINT("All done");
  return out;
}