Exemplo n.º 1
0
static event_t *
sendpkt(rtmp_t *r, media_queue_t *mq, media_codec_t *mc,
	int64_t dts, int64_t pts, const void *data, 
	size_t size, int skip, int dt, int duration, int drive_clock)
{
  event_t *e = NULL;
  media_buf_t *mb = media_buf_alloc_unlocked(r->mp, size);

  mb->mb_data_type = dt;
  mb->mb_duration = duration;
  mb->mb_cw = media_codec_ref(mc);
  mb->mb_drive_clock = drive_clock;
  mb->mb_dts = dts;
  mb->mb_pts = pts;
  mb->mb_skip = skip;
	
  memcpy(mb->mb_data, data, size);

  do {

    if(mb == NULL || (e = mb_enqueue_with_events(r->mp, mq, mb)) == NULL) {
      mb = NULL;
      break;
    }

    e = rtmp_process_event(r, e, &mb);

  } while(e == NULL);

  if(mb != NULL)
    media_buf_free_unlocked(r->mp, mb);

  return e;
}
Exemplo n.º 2
0
static void
dvd_video_push(dvd_player_t *dp)
{
  media_buf_t *mb;
  media_codec_t *cw = dp->dp_video;
  media_pipe_t *mp = dp->dp_mp;

  if(cw == NULL)
    return;

  mb = media_buf_alloc();
  mb->mb_cw = media_codec_ref(cw);
  mb->mb_size = 0;
  mb->mb_data = NULL;
  mb->mb_aspect_override = dp->dp_aspect_override;
  mb->mb_disable_deinterlacer = 1;
  mb->mb_data_type = MB_VIDEO;
  mb->mb_duration = cw->codec_ctx->ticks_per_frame * 
    1000000LL * av_q2d(cw->codec_ctx->time_base);
  mb->mb_pts = AV_NOPTS_VALUE;
  mb->mb_dts = AV_NOPTS_VALUE;
  mb->mb_epoch = dp->dp_epoch;

  mb_enqueue_always(mp, &mp->mp_video, mb);
}
Exemplo n.º 3
0
static event_t *
sendpkt(rtmp_t *r, media_queue_t *mq, media_codec_t *mc,
	int64_t dts, int64_t pts, int64_t time, const void *data, 
	size_t size, int skip, int dt, int duration)
{
  event_t *e = NULL;
  media_buf_t *mb = media_buf_alloc_unlocked(r->mp, size);

  mb->mb_data_type = dt;
  mb->mb_duration = duration;
  mb->mb_cw = media_codec_ref(mc);
  mb->mb_time = time;
  mb->mb_dts = dts;
  mb->mb_pts = pts;
  mb->mb_skip = skip;
  mb->mb_send_pts = dt == MB_VIDEO;
	
  memcpy(mb->mb_data, data, size);
  mb->mb_epoch = r->epoch;

  do {

    if(mb == NULL || (e = mb_enqueue_with_events(r->mp, mq, mb)) == NULL)
      break;
    
    e = rtmp_process_event(r, e, &mb);

  } while(e == NULL);

  return e;
}
Exemplo n.º 4
0
static event_t *
sendpkt(rtmp_t *r, media_queue_t *mq, media_codec_t *mc,
	int64_t dts, int64_t pts, int64_t time, const void *data, 
	size_t size, int skip, int dt, int duration)
{
  event_t *e = NULL;
  media_buf_t *mb = media_buf_alloc();

  mb->mb_data_type = dt;
  mb->mb_duration = duration;
  mb->mb_cw = media_codec_ref(mc);
  mb->mb_time = time;
  mb->mb_dts = dts;
  mb->mb_pts = pts;
  mb->mb_skip = skip;

  mb->mb_data = malloc(size +   FF_INPUT_BUFFER_PADDING_SIZE);
  memset(mb->mb_data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
  memcpy(mb->mb_data, data, size);
  mb->mb_size = size;
  mb->mb_epoch = r->epoch;

  do {

    if(mb == NULL || (e = mb_enqueue_with_events(r->mp, mq, mb)) == NULL)
      break;
    
    e = rtmp_process_event(r, e, &mb);

  } while(e == NULL);

  return e;
}
Exemplo n.º 5
0
static int
rvd_set_codec(media_codec_t *mc, glw_video_t *gv, const frame_info_t *fi)
{
  media_pipe_t *mp = gv->gv_mp;

  glw_video_configure(gv, &glw_video_rvd);

  gv->gv_width = fi->fi_width;
  gv->gv_height = fi->fi_height;

  rpi_video_display_t *rvd = gv->gv_aux;
  rpi_video_codec_t *rvc = mc->opaque;
  

  if(rvd->rvd_vrender == NULL) {

    rvd->rvd_vrender = omx_component_create("OMX.broadcom.video_render",
					    &rvd->rvd_mutex, NULL);
    rvd->rvd_vsched  = omx_component_create("OMX.broadcom.video_scheduler",
                                            &rvd->rvd_mutex, NULL);

    rvd->rvd_vsched->oc_opaque = rvd;
    rvd->rvd_vrender->oc_opaque = rvd;

    gv->gv_vd->vd_render_component = rvd->rvd_vrender;
       
    omx_enable_buffer_marks(rvd->rvd_vrender);

    rvd->rvd_tun_clock_vsched =
      omx_tunnel_create(omx_get_clock(mp), 81, rvd->rvd_vsched, 12,
			"clock -> vsched");
    
    rvd->rvd_vsched->oc_port_settings_changed_cb =
      vsched_port_settings_changed;

    rvd->rvd_vrender->oc_event_mark_cb = buffer_mark;

  }
  omx_set_state(rvd->rvd_vrender, OMX_StateIdle);

  if(rvd->rvd_tun_vdecoder_vsched != NULL)
    omx_tunnel_destroy(rvd->rvd_tun_vdecoder_vsched);
      
  if(rvd->rvd_mc != NULL)
    media_codec_deref(rvd->rvd_mc);

  rvd->rvd_mc = media_codec_ref(mc);

  rvd->rvd_tun_vdecoder_vsched =
    omx_tunnel_create(rvc->rvc_decoder, 131, rvd->rvd_vsched, 10,
		      "vdecoder -> vsched");

  omx_set_state(rvd->rvd_vsched,  OMX_StateExecuting);
  return 0;
}
Exemplo n.º 6
0
static event_t *
dvd_media_enqueue(dvd_player_t *dp, media_queue_t *mq, media_codec_t *cw,
		  int data_type, void *data, int datalen, int rate,
		  int64_t dts, int64_t pts)
{
  media_buf_t *mb = media_buf_alloc_unlocked(dp->dp_mp, datalen);
  event_t *e;

  AVCodecContext *ctx = cw->codec_ctx;

  mb->mb_cw = media_codec_ref(cw);
  mb->mb_data_type = data_type;
  mb->mb_duration = cw->codec_ctx->ticks_per_frame * 
    1000000LL * av_q2d(ctx->time_base);
  mb->mb_aspect_override = dp->dp_aspect_override;
  mb->mb_disable_deinterlacer = 1;
  mb->mb_dts = dts;
  mb->mb_pts = pts;

  
  if(pts != AV_NOPTS_VALUE && data_type == MB_VIDEO) {
    if(dp->dp_time_pts_delta == AV_NOPTS_VALUE) {
      int64_t t = av_rescale_q(dvdnav_get_current_time(dp->dp_dvdnav),
			       mpeg_tc, AV_TIME_BASE_Q);
      dp->dp_time_pts_delta = pts - t;
    }
    mb->mb_time = pts - dp->dp_time_pts_delta;
  } else {
    mb->mb_time = AV_NOPTS_VALUE;
  }

  memcpy(mb->mb_data, data, datalen);

  do {

    if((e = mb_enqueue_with_events(dp->dp_mp, mq, mb)) == NULL) {
      mb = NULL;
      break;
    }

    e = dvd_process_event(dp, e);

  } while(e == NULL);

  if(mb != NULL)
    media_buf_free_unlocked(dp->dp_mp, mb);

  return e;
}
Exemplo n.º 7
0
static event_t *
dvd_media_enqueue(dvd_player_t *dp, media_queue_t *mq, media_codec_t *cw,
		  int data_type, void *data, int datalen, int rate,
		  int64_t dts, int64_t pts)
{
  media_buf_t *mb = media_buf_alloc();
  event_t *e;

  AVCodecContext *ctx = cw->codec_ctx;

  mb->mb_cw = media_codec_ref(cw);
  mb->mb_data_type = data_type;
  mb->mb_duration = cw->codec_ctx->ticks_per_frame * 
    1000000LL * av_q2d(ctx->time_base);
  mb->mb_aspect_override = dp->dp_aspect_override;
  mb->mb_disable_deinterlacer = 1;
  mb->mb_dts = dts;
  mb->mb_pts = pts;
  //  mb->mb_time = (dvdnav_get_current_time(dp->dp_dvdnav) * 1000000) / 90000;
  mb->mb_epoch = dp->dp_epoch;
  
  mb->mb_data = malloc(datalen + FF_INPUT_BUFFER_PADDING_SIZE);
  mb->mb_size = datalen;
  memcpy(mb->mb_data, data, datalen);
  memset(mb->mb_data + datalen, 0, FF_INPUT_BUFFER_PADDING_SIZE);

  do {

    if((e = mb_enqueue_with_events(dp->dp_mp, mq, mb)) == NULL)
      break;
    
    e = dvd_process_event(dp, e);

  } while(e == NULL);

  return e;
}
Exemplo n.º 8
0
event_t *
be_file_playaudio(const char *url, media_pipe_t *mp,
		  char *errbuf, size_t errlen, int hold, const char *mimetype)
{
  AVFormatContext *fctx;
  AVCodecContext *ctx;
  AVPacket pkt;
  media_format_t *fw;
  int i, r, si;
  media_buf_t *mb = NULL;
  media_queue_t *mq;
  event_ts_t *ets;
  int64_t ts, seekbase = 0;
  media_codec_t *cw;
  event_t *e;
  int lost_focus = 0;
  int registered_play = 0;

  mp_set_playstatus_by_hold(mp, hold, NULL);

  fa_handle_t *fh = fa_open_ex(url, errbuf, errlen, FA_BUFFERED_SMALL, NULL);
  if(fh == NULL)
    return NULL;

  // First we need to check for a few other formats
#if ENABLE_LIBOPENSPC || ENABLE_LIBGME

  uint8_t pb[128];
  size_t psiz;
  
  psiz = fa_read(fh, pb, sizeof(pb));
  if(psiz < sizeof(pb)) {
    fa_close(fh);
    snprintf(errbuf, errlen, "Fill too small");
    return NULL;
  }

#if ENABLE_LIBGME
  if(*gme_identify_header(pb))
    return fa_gme_playfile(mp, fh, errbuf, errlen, hold, url);
#endif

#if ENABLE_LIBOPENSPC
  if(!memcmp(pb, "SNES-SPC700 Sound File Data", 27))
    return openspc_play(mp, fh, errbuf, errlen);
#endif

#endif

  
  AVIOContext *avio = fa_libav_reopen(fh);

  if(avio == NULL) {
    fa_close(fh);
    return NULL;
  }

  if((fctx = fa_libav_open_format(avio, url, 
				  errbuf, errlen, mimetype)) == NULL) {
    fa_libav_close(avio);
    return NULL;
  }

  TRACE(TRACE_DEBUG, "Audio", "Starting playback of %s", url);

  mp_configure(mp, MP_PLAY_CAPS_SEEK | MP_PLAY_CAPS_PAUSE,
	       MP_BUFFER_SHALLOW);

  mp->mp_audio.mq_stream = -1;
  mp->mp_video.mq_stream = -1;

  fw = media_format_create(fctx);

  cw = NULL;
  for(i = 0; i < fctx->nb_streams; i++) {
    ctx = fctx->streams[i]->codec;

    if(ctx->codec_type != AVMEDIA_TYPE_AUDIO)
      continue;

    cw = media_codec_create(ctx->codec_id, 0, fw, ctx, NULL, mp);
    mp->mp_audio.mq_stream = i;
    break;
  }
  
  if(cw == NULL) {
    media_format_deref(fw);
    snprintf(errbuf, errlen, "Unable to open codec");
    return NULL;
  }

  mp_become_primary(mp);
  mq = &mp->mp_audio;

  while(1) {

    /**
     * Need to fetch a new packet ?
     */
    if(mb == NULL) {
      
      mp->mp_eof = 0;
      r = av_read_frame(fctx, &pkt);
      if(r == AVERROR(EAGAIN))
	continue;
      
      if(r == AVERROR_EOF || r == AVERROR(EIO)) {
	mb = MB_SPECIAL_EOF;
	mp->mp_eof = 1;
	continue;
      }
      
      if(r != 0) {
	char msg[100];
	fa_ffmpeg_error_to_txt(r, msg, sizeof(msg));
	TRACE(TRACE_ERROR, "Audio", "Playback error: %s", msg);

	while((e = mp_wait_for_empty_queues(mp)) != NULL) {
	  if(event_is_type(e, EVENT_PLAYQUEUE_JUMP) ||
	     event_is_action(e, ACTION_PREV_TRACK) ||
	     event_is_action(e, ACTION_NEXT_TRACK) ||
	     event_is_action(e, ACTION_STOP)) {
	    mp_flush(mp, 0);
	    break;
	  }
	  event_release(e);
	}
	if(e == NULL)
	  e = event_create_type(EVENT_EOF);
	break;
      }

      si = pkt.stream_index;

      if(si != mp->mp_audio.mq_stream) {
	av_free_packet(&pkt);
	continue;
      }



      mb = media_buf_alloc_unlocked(mp, pkt.size);
      mb->mb_data_type = MB_AUDIO;

      mb->mb_pts      = rescale(fctx, pkt.pts,      si);
      mb->mb_dts      = rescale(fctx, pkt.dts,      si);
      mb->mb_duration = rescale(fctx, pkt.duration, si);

      mb->mb_cw = media_codec_ref(cw);

      /* Move the data pointers from ffmpeg's packet */

      mb->mb_stream = pkt.stream_index;

      memcpy(mb->mb_data, pkt.data, pkt.size);

      if(mb->mb_pts != AV_NOPTS_VALUE) {
	if(fctx->start_time == AV_NOPTS_VALUE)
	  mb->mb_time = mb->mb_pts;
	else
	  mb->mb_time = mb->mb_pts - fctx->start_time;
      } else
	mb->mb_time = AV_NOPTS_VALUE;

      mb->mb_send_pts = 1;

      av_free_packet(&pkt);
    }

    /*
     * Try to send the buffer.  If mb_enqueue() returns something we
     * catched an event instead of enqueueing the buffer. In this case
     * 'mb' will be left untouched.
     */

    if(mb == MB_SPECIAL_EOF) {
      // We have reached EOF, drain queues
      e = mp_wait_for_empty_queues(mp);
      
      if(e == NULL) {
	e = event_create_type(EVENT_EOF);
	break;
      }

    } else if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) {
      mb = NULL; /* Enqueue succeeded */
      continue;
    }      

    if(event_is_type(e, EVENT_PLAYQUEUE_JUMP)) {

      mp_flush(mp, 0);
      break;

    } else if(event_is_type(e, EVENT_CURRENT_PTS)) {

      ets = (event_ts_t *)e;
      seekbase = ets->ts;

      if(registered_play == 0) {
	if(ets->ts - fctx->start_time > METADB_AUDIO_PLAY_THRESHOLD) {
	  registered_play = 1;
	  metadb_register_play(url, 1, CONTENT_AUDIO);
	}
      }

    } else if(event_is_type(e, EVENT_SEEK)) {

      ets = (event_ts_t *)e;
      ts = ets->ts + fctx->start_time;
      if(ts < fctx->start_time)
	ts = fctx->start_time;
      av_seek_frame(fctx, -1, ts, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);
      
    } else if(event_is_action(e, ACTION_SEEK_FAST_BACKWARD)) {

      av_seek_frame(fctx, -1, seekbase - 60000000, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);

    } else if(event_is_action(e, ACTION_SEEK_BACKWARD)) {

      av_seek_frame(fctx, -1, seekbase - 15000000, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);

    } else if(event_is_action(e, ACTION_SEEK_FAST_FORWARD)) {

      av_seek_frame(fctx, -1, seekbase + 60000000, 0);
      seekflush(mp, &mb);

    } else if(event_is_action(e, ACTION_SEEK_FORWARD)) {

      av_seek_frame(fctx, -1, seekbase + 15000000, 0);
      seekflush(mp, &mb);
#if 0
    } else if(event_is_action(e, ACTION_RESTART_TRACK)) {

      av_seek_frame(fctx, -1, 0, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);
#endif
    } else if(event_is_action(e, ACTION_PLAYPAUSE) ||
	      event_is_action(e, ACTION_PLAY) ||
	      event_is_action(e, ACTION_PAUSE)) {

      hold = action_update_hold_by_event(hold, e);
      mp_send_cmd_head(mp, mq, hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY);
      lost_focus = 0;
      mp_set_playstatus_by_hold(mp, hold, NULL);

    } else if(event_is_type(e, EVENT_MP_NO_LONGER_PRIMARY)) {

      hold = 1;
      lost_focus = 1;
      mp_send_cmd_head(mp, mq, MB_CTRL_PAUSE);
      mp_set_playstatus_by_hold(mp, hold, e->e_payload);

    } else if(event_is_type(e, EVENT_MP_IS_PRIMARY)) {

      if(lost_focus) {
	hold = 0;
	lost_focus = 0;
	mp_send_cmd_head(mp, mq, MB_CTRL_PLAY);
	mp_set_playstatus_by_hold(mp, hold, NULL);
      }

    } else if(event_is_type(e, EVENT_INTERNAL_PAUSE)) {

      hold = 1;
      lost_focus = 0;
      mp_send_cmd_head(mp, mq, MB_CTRL_PAUSE);
      mp_set_playstatus_by_hold(mp, hold, e->e_payload);

    } else if(event_is_action(e, ACTION_PREV_TRACK) ||
	      event_is_action(e, ACTION_NEXT_TRACK) ||
	      event_is_action(e, ACTION_STOP)) {
      mp_flush(mp, 0);
      break;
    }
    event_release(e);
  }

  if(mb != NULL && mb != MB_SPECIAL_EOF)
    media_buf_free_unlocked(mp, mb);

  media_codec_deref(cw);
  media_format_deref(fw);

  if(hold) { 
    // If we were paused, release playback again.
    mp_send_cmd(mp, mq, MB_CTRL_PLAY);
    mp_set_playstatus_by_hold(mp, 0, NULL);
  }

  return e;
}
Exemplo n.º 9
0
event_t *
be_file_playaudio(const char *url, media_pipe_t *mp,
		  char *errbuf, size_t errlen, int hold)
{
  AVFormatContext *fctx;
  AVIOContext *avio;
  AVCodecContext *ctx;
  AVPacket pkt;
  media_format_t *fw;
  int i, r, si;
  media_buf_t *mb = NULL;
  media_queue_t *mq;
  event_ts_t *ets;
  int64_t ts, pts4seek = 0;
  media_codec_t *cw;
  event_t *e;
  int lost_focus = 0;

  mp_set_playstatus_by_hold(mp, hold, NULL);

  if((avio = fa_libav_open(url, 32768, errbuf, errlen)) == NULL)
    return NULL;


  // First we need to check for a few other formats
#if ENABLE_LIBOPENSPC || ENABLE_LIBGME

  uint8_t pb[128];
  size_t psiz;
  
  psiz = avio_read(avio, pb, sizeof(pb));
  if(psiz < sizeof(pb)) {
    fa_libav_close(avio);
    snprintf(errbuf, errlen, "Fill too small");
    return NULL;
  }

#if ENABLE_LIBGME
  if(*gme_identify_header(pb))
    return fa_gme_playfile(mp, avio, errbuf, errlen, hold);
#endif

#if ENABLE_LIBOPENSPC
  if(!memcmp(pb, "SNES-SPC700 Sound File Data", 27))
    return openspc_play(mp, avio, errbuf, errlen);
#endif

#endif

  if((fctx = fa_libav_open_format(avio, url, errbuf, errlen)) == NULL) {
    fa_libav_close(avio);
    return NULL;
  }

  TRACE(TRACE_DEBUG, "Audio", "Starting playback of %s", url);

  mp_set_play_caps(mp, MP_PLAY_CAPS_SEEK | MP_PLAY_CAPS_PAUSE);

  mp->mp_audio.mq_stream = -1;
  mp->mp_video.mq_stream = -1;

  fw = media_format_create(fctx);

  cw = NULL;
  for(i = 0; i < fctx->nb_streams; i++) {
    ctx = fctx->streams[i]->codec;

    if(ctx->codec_type != AVMEDIA_TYPE_AUDIO)
      continue;

    cw = media_codec_create(ctx->codec_id, 0, fw, ctx, NULL, mp);
    mp->mp_audio.mq_stream = i;
    break;
  }
  
  if(cw == NULL) {
    media_format_deref(fw);
    snprintf(errbuf, errlen, "Unable to open codec");
    return NULL;
  }

  mp_become_primary(mp);
  mq = &mp->mp_audio;

  while(1) {

    /**
     * Need to fetch a new packet ?
     */
    if(mb == NULL) {

      if((r = av_read_frame(fctx, &pkt)) < 0) {

	while((e = mp_wait_for_empty_queues(mp, 0)) != NULL) {
	  if(event_is_type(e, EVENT_PLAYQUEUE_JUMP) ||
	     event_is_action(e, ACTION_PREV_TRACK) ||
	     event_is_action(e, ACTION_NEXT_TRACK) ||
	     event_is_action(e, ACTION_STOP)) {
	    mp_flush(mp, 0);
	    break;
	  }
	  event_release(e);
	}
	if(e == NULL)
	  e = event_create_type(EVENT_EOF);
	break;
      }

      si = pkt.stream_index;

      if(si == mp->mp_audio.mq_stream) {
	/* Current audio stream */
	mb = media_buf_alloc();
	mb->mb_data_type = MB_AUDIO;

      } else {
	/* Check event queue ? */
	av_free_packet(&pkt);
	continue;
      }


      mb->mb_pts      = rescale(fctx, pkt.pts,      si);
      mb->mb_dts      = rescale(fctx, pkt.dts,      si);
      mb->mb_duration = rescale(fctx, pkt.duration, si);

      mb->mb_cw = media_codec_ref(cw);

      /* Move the data pointers from ffmpeg's packet */

      mb->mb_stream = pkt.stream_index;

      av_dup_packet(&pkt);

      mb->mb_data = pkt.data;
      pkt.data = NULL;

      mb->mb_size = pkt.size;
      pkt.size = 0;

      if(mb->mb_pts != AV_NOPTS_VALUE) {
	if(fctx->start_time == AV_NOPTS_VALUE)
	  mb->mb_time = mb->mb_pts;
	else
	  mb->mb_time = mb->mb_pts - fctx->start_time;
	pts4seek = mb->mb_time;
      } else
	mb->mb_time = AV_NOPTS_VALUE;


      av_free_packet(&pkt);
    }

    /*
     * Try to send the buffer.  If mb_enqueue() returns something we
     * catched an event instead of enqueueing the buffer. In this case
     * 'mb' will be left untouched.
     */

    if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) {
      mb = NULL; /* Enqueue succeeded */
      continue;
    }      

    if(event_is_type(e, EVENT_PLAYQUEUE_JUMP)) {

      mp_flush(mp, 0);
      break;

    } else if(event_is_type(e, EVENT_SEEK)) {

      ets = (event_ts_t *)e;
      ts = ets->pts + fctx->start_time;
      if(ts < fctx->start_time)
	ts = fctx->start_time;
      av_seek_frame(fctx, -1, ts, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);
      
    } else if(event_is_action(e, ACTION_SEEK_FAST_BACKWARD)) {

      av_seek_frame(fctx, -1, pts4seek - 60000000, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);

    } else if(event_is_action(e, ACTION_SEEK_BACKWARD)) {

      av_seek_frame(fctx, -1, pts4seek - 15000000, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);

    } else if(event_is_action(e, ACTION_SEEK_FAST_FORWARD)) {

      av_seek_frame(fctx, -1, pts4seek + 60000000, 0);
      seekflush(mp, &mb);

    } else if(event_is_action(e, ACTION_SEEK_FORWARD)) {

      av_seek_frame(fctx, -1, pts4seek + 15000000, 0);
      seekflush(mp, &mb);
#if 0
    } else if(event_is_action(e, ACTION_RESTART_TRACK)) {

      av_seek_frame(fctx, -1, 0, AVSEEK_FLAG_BACKWARD);
      seekflush(mp, &mb);
#endif
    } else if(event_is_action(e, ACTION_PLAYPAUSE) ||
	      event_is_action(e, ACTION_PLAY) ||
	      event_is_action(e, ACTION_PAUSE)) {

      hold = action_update_hold_by_event(hold, e);
      mp_send_cmd_head(mp, mq, hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY);
      lost_focus = 0;
      mp_set_playstatus_by_hold(mp, hold, NULL);

    } else if(event_is_type(e, EVENT_MP_NO_LONGER_PRIMARY)) {

      hold = 1;
      lost_focus = 1;
      mp_send_cmd_head(mp, mq, MB_CTRL_PAUSE);
      mp_set_playstatus_by_hold(mp, hold, e->e_payload);

    } else if(event_is_type(e, EVENT_MP_IS_PRIMARY)) {

      if(lost_focus) {
	hold = 0;
	lost_focus = 0;
	mp_send_cmd_head(mp, mq, MB_CTRL_PLAY);
	mp_set_playstatus_by_hold(mp, hold, NULL);
      }

    } else if(event_is_type(e, EVENT_INTERNAL_PAUSE)) {

      hold = 1;
      lost_focus = 0;
      mp_send_cmd_head(mp, mq, MB_CTRL_PAUSE);
      mp_set_playstatus_by_hold(mp, hold, e->e_payload);

    } else if(event_is_action(e, ACTION_PREV_TRACK) ||
	      event_is_action(e, ACTION_NEXT_TRACK) ||
	      event_is_action(e, ACTION_STOP)) {
      mp_flush(mp, 0);
      break;
    }
    event_release(e);
  }

  if(mb != NULL)
    media_buf_free(mb);

  media_codec_deref(cw);
  media_format_deref(fw);

  if(hold) { 
    // If we were paused, release playback again.
    mp_send_cmd(mp, mq, MB_CTRL_PLAY);
    mp_set_playstatus_by_hold(mp, 0, NULL);
  }

  return e;
}
Exemplo n.º 10
0
static void *
test_generator_thread(void *aux)
{
  media_pipe_t *mp = aux;
  media_buf_t *mb = NULL;
  event_t *e;
  media_queue_t *mq = &mp->mp_audio;
  pcm_sound_t voices[8];
  AVFrame *frame = av_frame_alloc();
  AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AC3);
  AVCodecContext *ctx = avcodec_alloc_context3(codec);

  ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
  ctx->sample_rate = 48000;
  ctx->channel_layout = AV_CH_LAYOUT_5POINT1;

  if(avcodec_open2(ctx, codec, NULL) < 0) {
    TRACE(TRACE_ERROR, "audio", "Unable to open encoder");
    return NULL;
  }

  float *genbuf[8];
  for(int i = 0; i < 8; i++) {
    genbuf[i] = av_malloc(ctx->frame_size * sizeof(float));
    frame->data[i] = (void *)genbuf[i];
  }

  frame->nb_samples = ctx->frame_size;

  media_codec_t *mc = media_codec_create(AV_CODEC_ID_AC3, 0,
					 NULL, NULL, NULL, mp);

  mp_set_playstatus_by_hold(mp, 0, NULL);
  mp->mp_audio.mq_stream = 0;
  mp_configure(mp, 0, MP_BUFFER_NONE, 0, "testsignal");
  mp_become_primary(mp);

  int sample = 0;

  unpack_speaker_positions(voices);

  while(1) {

    if(mb == NULL) {

      int got_packet;
      AVPacket pkt = {0};

      generator_t *g;

      switch(signal_type) {

      case 0:
	for(int c = 0; c < 8; c++) {
	  int z = ctx->frame_size;
	  if(test_channels[c]) {

	    int j = sample & 0xffff;
	    int to_copy = MIN(ctx->frame_size, (voices[c].samples - j));

	    if(to_copy < 0)
	      to_copy = 0;

	    for(int i = 0; i < to_copy; i++) {
	      genbuf[c][i] = voices[c].data[j+i] / 32767.0f;
	    }
	    z = ctx->frame_size - to_copy;
	  }
	  memset(genbuf[c] + ctx->frame_size - z, 0, sizeof(float) * z);
	}
	sample += ctx->frame_size;

	goto encode;
	
      default: g = &gen_pink_noise; break;
      case 2:  g = &gen_sinewave;   break;
      }
	
      for(int i = 0; i < ctx->frame_size; i++) {
	float x = g(sample);
	for(int c = 0; c < 8; c++) {
	  genbuf[c][i] = test_channels[c] ? x : 0;
	}
	sample++;
      }

    encode:
      av_init_packet(&pkt);
      int r = avcodec_encode_audio2(ctx, &pkt, frame, &got_packet);
      if(!r && got_packet) {
	mb = media_buf_from_avpkt_unlocked(mp, &pkt);
	av_free_packet(&pkt);
      } else {
	sleep(1);
      }

      mb->mb_cw = media_codec_ref(mc);

      mb->mb_data_type = MB_AUDIO;
      mb->mb_pts = PTS_UNSET;

    }

    if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) {
      mb = NULL; /* Enqueue succeeded */
      continue;
    }

    if(event_is_type(e, EVENT_EXIT)) {
      mp_flush(mp, 0);
      break;
    }
    event_release(e);
  }  
  av_frame_free(&frame);

  for(int i = 0; i < 8; i++)
    av_freep(&genbuf[i]);

  for(int i = 0; i < 8; i++)
    free(voices[i].data);

  media_codec_deref(mc);

  return NULL;
}
Exemplo n.º 11
0
/**
 * Video decoder thread
 */
static void *
vd_thread(void *aux)
{
  video_decoder_t *vd = aux;
  media_pipe_t *mp = vd->vd_mp;
  media_queue_t *mq = &mp->mp_video;
  media_buf_t *mb;
  media_buf_t *cur = NULL;
  media_codec_t *mc, *mc_current = NULL;
  int run = 1;
  int reqsize = -1;
  int size;
  int reinit = 0;

  const media_buf_meta_t *mbm = NULL;

  vd->vd_frame = av_frame_alloc();

  hts_mutex_lock(&mp->mp_mutex);

  while(run) {

    if(mbm != vd->vd_reorder_current) {
      mbm = vd->vd_reorder_current;
      hts_mutex_unlock(&mp->mp_mutex);

      vd->vd_estimated_duration = mbm->mbm_duration;

      video_decoder_set_current_time(vd, mbm->mbm_pts, mbm->mbm_epoch,
				     mbm->mbm_delta);
      hts_mutex_lock(&mp->mp_mutex);
      continue;
    }

    media_buf_t *ctrl = TAILQ_FIRST(&mq->mq_q_ctrl);
    media_buf_t *data = TAILQ_FIRST(&mq->mq_q_data);
    media_buf_t *aux  = TAILQ_FIRST(&mq->mq_q_aux);

    if(ctrl != NULL) {
      TAILQ_REMOVE(&mq->mq_q_ctrl, ctrl, mb_link);
      mb = ctrl;

    } else if(aux != NULL && aux->mb_pts < vd->vd_subpts + 1000000LL) {

      if(vd->vd_hold) {
	hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
	continue;
      }

      TAILQ_REMOVE(&mq->mq_q_aux, aux, mb_link);
      mb = aux;

    } else if(cur != NULL) {

      if(vd->vd_hold) {
	hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
	continue;
      }

      mb = cur;
      goto retry_current;
    } else if(data != NULL) {

      if(vd->vd_hold) {
	hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
	continue;
      }

      TAILQ_REMOVE(&mq->mq_q_data, data, mb_link);
      mp_check_underrun(mp);
      mb = data;

    } else {
      hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
      continue;
    }


    mq->mq_packets_current--;
    mp->mp_buffer_current -= mb->mb_size;
    mq_update_stats(mp, mq);

    hts_cond_signal(&mp->mp_backpressure);

  retry_current:
    mc = mb->mb_cw;

    if(mb->mb_data_type == MB_VIDEO && mc->decode_locked != NULL) {

      if(mc != mc_current) {
	if(mc_current != NULL)
	  media_codec_deref(mc_current);

	mc_current = media_codec_ref(mc);
	prop_set_int(mq->mq_prop_too_slow, 0);
      }

      size = mb->mb_size;

      mq->mq_no_data_interest = 1;
      if(mc->decode_locked(mc, vd, mq, mb)) {
        cur = mb;
 	hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
        continue;
      }
      mq->mq_no_data_interest = 0;
      cur = NULL;

      update_vbitrate(mp, mq, size, vd);
      media_buf_free_locked(mp, mb);
      continue;
    }

    hts_mutex_unlock(&mp->mp_mutex);


    switch(mb->mb_data_type) {
    case MB_CTRL_EXIT:
      run = 0;
      break;

    case MB_CTRL_PAUSE:
      vd->vd_hold = 1;
      break;

    case MB_CTRL_PLAY:
      vd->vd_hold = 0;
      break;

    case MB_CTRL_FLUSH:
      if(cur != NULL) {
        media_buf_free_unlocked(mp, cur);
        mq->mq_no_data_interest = 0;
        cur = NULL;
      }
      vd_init_timings(vd);
      vd->vd_interlaced = 0;

      hts_mutex_lock(&mp->mp_overlay_mutex);
      video_overlay_flush_locked(mp, 1);
      dvdspu_flush_locked(mp);
      hts_mutex_unlock(&mp->mp_overlay_mutex);

      mp->mp_video_frame_deliver(NULL, mp->mp_video_frame_opaque);

      if(mc_current != NULL) {
        mc_current->flush(mc_current, vd);
	media_codec_deref(mc_current);
	mc_current = NULL;
      }

      mp->mp_video_frame_deliver(NULL, mp->mp_video_frame_opaque);
      if(mp->mp_seek_video_done != NULL)
	mp->mp_seek_video_done(mp);
      break;

    case MB_VIDEO:
      if(mc != mc_current) {
	if(mc_current != NULL)
	  media_codec_deref(mc_current);

	mc_current = media_codec_ref(mc);
	prop_set_int(mq->mq_prop_too_slow, 0);
      }

      if(reinit) {
	if(mc->reinit != NULL)
	  mc->reinit(mc);
	reinit = 0;
      }

      size = mb->mb_size;

      mc->decode(mc, vd, mq, mb, reqsize);
      update_vbitrate(mp, mq, size, vd);
      reqsize = -1;
      break;

    case MB_CTRL_REQ_OUTPUT_SIZE:
      reqsize = mb->mb_data32;
      break;

    case MB_CTRL_REINITIALIZE:
      reinit = 1;
      break;

    case MB_CTRL_RECONFIGURE:
      mb->mb_cw->reconfigure(mc, mb->mb_frame_info);
      break;

#if ENABLE_DVD
    case MB_DVD_RESET_SPU:
      hts_mutex_lock(&mp->mp_overlay_mutex);
      vd->vd_spu_curbut = 1;
      dvdspu_flush_locked(mp);
      hts_mutex_unlock(&mp->mp_overlay_mutex);
      break;

    case MB_CTRL_DVD_HILITE:
      vd->vd_spu_curbut = mb->mb_data32;
      vd->vd_spu_repaint = 1;
      break;

    case MB_DVD_PCI:
      memcpy(&vd->vd_pci, mb->mb_data, sizeof(pci_t));
      vd->vd_spu_repaint = 1;
      event_payload_t *ep =
        event_create(EVENT_DVD_PCI, sizeof(event_t) + sizeof(pci_t));
      memcpy(ep->payload, mb->mb_data, sizeof(pci_t));
      mp_enqueue_event(mp, &ep->h);
      event_release(&ep->h);
      break;

    case MB_DVD_CLUT:
      dvdspu_decode_clut(vd->vd_dvd_clut, (void *)mb->mb_data);
      break;

    case MB_DVD_SPU:
      dvdspu_enqueue(mp, mb->mb_data, mb->mb_size, 
		     vd->vd_dvd_clut, 0, 0, mb->mb_pts);
      break;
#endif

    case MB_CTRL_DVD_SPU2:
      dvdspu_enqueue(mp, mb->mb_data+72, mb->mb_size-72,
		     (void *)mb->mb_data,
		     ((const uint32_t *)mb->mb_data)[16],
		     ((const uint32_t *)mb->mb_data)[17],
		     mb->mb_pts);
      break;
      


    case MB_SUBTITLE:
      if(vd->vd_ext_subtitles == NULL && mb->mb_stream == mq->mq_stream2)
	video_overlay_decode(mp, mb);
      break;

    case MB_CTRL_FLUSH_SUBTITLES:
      hts_mutex_lock(&mp->mp_overlay_mutex);
      video_overlay_flush_locked(mp, 1);
      hts_mutex_unlock(&mp->mp_overlay_mutex);
      break;

    case MB_CTRL_EXT_SUBTITLE:
      if(vd->vd_ext_subtitles != NULL)
         subtitles_destroy(vd->vd_ext_subtitles);

      // Steal subtitle from the media_buf
      vd->vd_ext_subtitles = (void *)mb->mb_data;
      mb->mb_data = NULL;
      hts_mutex_lock(&mp->mp_overlay_mutex);
      video_overlay_flush_locked(mp, 1);
      hts_mutex_unlock(&mp->mp_overlay_mutex);
      break;

    default:
      abort();
    }

    hts_mutex_lock(&mp->mp_mutex);
    media_buf_free_locked(mp, mb);
  }

  if(cur != NULL)
    media_buf_free_locked(mp, cur);

  mq->mq_no_data_interest = 0;

  hts_mutex_unlock(&mp->mp_mutex);

  if(mc_current != NULL)
    media_codec_deref(mc_current);

  if(vd->vd_ext_subtitles != NULL)
    subtitles_destroy(vd->vd_ext_subtitles);

  av_frame_free(&vd->vd_frame);
  return NULL;
}