示例#1
0
/**
 * Get a list of supported containers
 */
int
muxer_container_list(htsmsg_t *array)
{
  htsmsg_t *mc;
  int c = 0;

  mc = htsmsg_create_map();
  htsmsg_add_str(mc, "name",        muxer_container_type2txt(MC_MATROSKA));
  htsmsg_add_str(mc, "description", "Matroska");
  htsmsg_add_msg(array, NULL, mc);
  c++;
  
  mc = htsmsg_create_map();
  htsmsg_add_str(mc, "name",        muxer_container_type2txt(MC_PASS));
  htsmsg_add_str(mc, "description", "Same as source (pass through)");
  htsmsg_add_msg(array, NULL, mc);
  c++;

#if ENABLE_LIBAV
  mc = htsmsg_create_map();
  htsmsg_add_str(mc, "name",        muxer_container_type2txt(MC_MPEGTS));
  htsmsg_add_str(mc, "description", "MPEG-TS");
  htsmsg_add_msg(array, NULL, mc);
  c++;

  mc = htsmsg_create_map();
  htsmsg_add_str(mc, "name",        muxer_container_type2txt(MC_MPEGPS));
  htsmsg_add_str(mc, "description", "MPEG-PS (DVD)");
  htsmsg_add_msg(array, NULL, mc);
  c++;
#endif

  return c;
}
示例#2
0
/**
 * Init the muxer with streams
 */
static int
lav_muxer_init(muxer_t* m, const struct streaming_start *ss, const char *name)
{
  int i;
  const streaming_start_component_t *ssc;
  AVFormatContext *oc;
  lav_muxer_t *lm = (lav_muxer_t*)m;
  char app[128];

  snprintf(app, sizeof(app), "Tvheadend %s", tvheadend_version);

  oc = lm->lm_oc;

  av_dict_set(&oc->metadata, "title", name, 0);
  av_dict_set(&oc->metadata, "service_name", name, 0);
  av_dict_set(&oc->metadata, "service_provider", app, 0);

  if(lm->m_container == MC_MPEGTS)
    lm->lm_h264_filter = av_bitstream_filter_init("h264_mp4toannexb");

  oc->max_delay = 0.7 * AV_TIME_BASE;

  for(i=0; i < ss->ss_num_components; i++) {
    ssc = &ss->ss_components[i];

    if(ssc->ssc_disabled)
      continue;

    if(!lav_muxer_support_stream(lm->m_container, ssc->ssc_type)) {
      tvhlog(LOG_WARNING, "libav",  "%s is not supported in %s", 
	     streaming_component_type2txt(ssc->ssc_type), 
	     muxer_container_type2txt(lm->m_container));
      continue;
    }

    if(lav_muxer_add_stream(lm, ssc)) {
      tvhlog(LOG_ERR, "libav",  "Failed to add %s stream", 
	     streaming_component_type2txt(ssc->ssc_type));
      continue;
    }
  }

  if(!lm->lm_oc->nb_streams) {
    tvhlog(LOG_ERR, "libav",  "No supported streams available");
    lm->m_errors++;
    return -1;
  } else if(avformat_write_header(lm->lm_oc, NULL) < 0) {
    tvhlog(LOG_ERR, "libav",  "Failed to write %s header", 
	   muxer_container_type2txt(lm->m_container));
    lm->m_errors++;
    return -1;
  }

  lm->lm_init = 1;

  return 0;
}
示例#3
0
/**
 * Create a new muxer
 */
muxer_t* 
muxer_create(muxer_container_type_t mc, const muxer_config_t *m_cfg)
{
  muxer_t *m;

  assert(m_cfg);

  m = pass_muxer_create(mc, m_cfg);

  if(!m)
    m = tvh_muxer_create(mc, m_cfg);

#if CONFIG_LIBAV
  if(!m)
    m = lav_muxer_create(mc, m_cfg);
#endif

  if(!m) {
    tvhlog(LOG_ERR, "mux", "Can't find a muxer that supports '%s' container",
	   muxer_container_type2txt(mc));
    return NULL;
  }
  
  memcpy(&m->m_config, m_cfg, sizeof(muxer_config_t));

  return m;
}
示例#4
0
/**
 * Create a new libavformat based muxer
 */
muxer_t*
lav_muxer_create(const muxer_config_t *m_cfg)
{
  const char *mux_name;
  lav_muxer_t *lm;
  AVOutputFormat *fmt;

  switch(m_cfg->m_type) {
  case MC_MPEGPS:
    mux_name = "dvd";
    break;
  case MC_MATROSKA:
  case MC_AVMATROSKA:
    mux_name = "matroska";
    break;
  case MC_WEBM:
  case MC_AVWEBM:
    mux_name = "webm";
    break;
  case MC_AVMP4:
    mux_name = "mp4";
    break;
  default:
    mux_name = muxer_container_type2txt(m_cfg->m_type);
    break;
  }

  fmt = av_guess_format(mux_name, NULL, NULL);
  if(!fmt) {
    tvherror(LS_LIBAV,  "Can't find the '%s' muxer", mux_name);
    return NULL;
  }

  lm = calloc(1, sizeof(lav_muxer_t));
  lm->m_open_stream  = lav_muxer_open_stream;
  lm->m_open_file    = lav_muxer_open_file;
  lm->m_init         = lav_muxer_init;
  lm->m_reconfigure  = lav_muxer_reconfigure;
  lm->m_mime         = lav_muxer_mime;
  lm->m_add_marker   = lav_muxer_add_marker;
  lm->m_write_meta   = lav_muxer_write_meta;
  lm->m_write_pkt    = lav_muxer_write_pkt;
  lm->m_close        = lav_muxer_close;
  lm->m_destroy      = lav_muxer_destroy;
  lm->lm_oc          = avformat_alloc_context();
  lm->lm_oc->oformat = fmt;
  lm->lm_fd          = -1;
  lm->lm_init        = 0;

  return (muxer_t*)lm;
}
示例#5
0
/**
 * Close the muxer and append trailer to output
 */
static int
lav_muxer_close(muxer_t *m)
{
  int ret = 0;
  lav_muxer_t *lm = (lav_muxer_t*)m;

  if(lm->lm_init && av_write_trailer(lm->lm_oc) < 0) {
    tvhlog(LOG_WARNING, "libav",  "Failed to write %s trailer", 
	   muxer_container_type2txt(lm->m_config.m_type));
    lm->m_errors++;
    ret = -1;
  }
  return ret;
}
示例#6
0
/**
 * Create a new libavformat based muxer
 */
muxer_t*
lav_muxer_create(muxer_container_type_t mc)
{
  const char *mux_name;
  lav_muxer_t *lm;
  AVOutputFormat *fmt;

  switch(mc) {
  case MC_MPEGPS:
    mux_name = "dvd";
    break;
  default:
    mux_name = muxer_container_type2txt(mc);
    break;
  }

  fmt = av_guess_format(mux_name, NULL, NULL);
  if(!fmt) {
    tvhlog(LOG_ERR, "libav",  "Can't find the '%s' muxer", mux_name);
    return NULL;
  }

  lm = calloc(1, sizeof(lav_muxer_t));
  lm->m_open_stream  = lav_muxer_open_stream;
  lm->m_open_file    = lav_muxer_open_file;
  lm->m_init         = lav_muxer_init;
  lm->m_reconfigure  = lav_muxer_reconfigure;
  lm->m_mime         = lav_muxer_mime;
  lm->m_add_marker   = lav_muxer_add_marker;
  lm->m_write_meta   = lav_muxer_write_meta;
  lm->m_write_pkt    = lav_muxer_write_pkt;
  lm->m_close        = lav_muxer_close;
  lm->m_destroy      = lav_muxer_destroy;
  lm->m_container    = mc;
  lm->lm_oc          = avformat_alloc_context();
  lm->lm_oc->oformat = fmt;
  lm->lm_fd          = -1;
  lm->lm_init        = 0;

  return (muxer_t*)lm;
}
示例#7
0
/**
 * Create a new muxer
 */
muxer_t* 
muxer_create(muxer_container_type_t mc)
{
  muxer_t *m;

  m = pass_muxer_create(mc);

  if(!m)
    m = tvh_muxer_create(mc);

#if ENABLE_LIBAV
  if(!m)
    m = lav_muxer_create(mc);
#endif

  if(!m)
    tvhlog(LOG_ERR, "mux", "Can't find a muxer that supports '%s' container",
	   muxer_container_type2txt(mc));

  return m;
}
示例#8
0
/**
 * Close the muxer and append trailer to output
 */
static int
lav_muxer_close(muxer_t *m)
{
  int i;
  int ret = 0;
  lav_muxer_t *lm = (lav_muxer_t*)m;

  if(lm->lm_init && av_write_trailer(lm->lm_oc) < 0) {
    tvhlog(LOG_WARNING, "libav",  "Failed to write %s trailer", 
	   muxer_container_type2txt(lm->m_container));
    lm->m_errors++;
    ret = -1;
  }

  if(lm->lm_h264_filter)
    av_bitstream_filter_close(lm->lm_h264_filter);

  for(i=0; i<lm->lm_oc->nb_streams; i++)
    av_freep(&lm->lm_oc->streams[i]->codec->extradata);
 
  lm->lm_oc->nb_streams = 0;

  return ret;
}
示例#9
0
/**
 * Init the muxer with streams
 */
static int
lav_muxer_init(muxer_t* m, struct streaming_start *ss, const char *name)
{
  int i;
  streaming_start_component_t *ssc;
  AVFormatContext *oc;
  AVDictionary *opts = NULL;
  lav_muxer_t *lm = (lav_muxer_t*)m;
  char app[128];

  snprintf(app, sizeof(app), "Tvheadend %s", tvheadend_version);

  oc = lm->lm_oc;

  av_dict_set(&oc->metadata, "title", name, 0);
  av_dict_set(&oc->metadata, "service_name", name, 0);
  av_dict_set(&oc->metadata, "service_provider", app, 0);

  if(lm->m_config.m_type == MC_MPEGTS) {
    lm->lm_h264_filter = av_bitstream_filter_init("h264_mp4toannexb");
    lm->lm_hevc_filter = av_bitstream_filter_init("hevc_mp4toannexb");
  }

  oc->max_delay = 0.7 * AV_TIME_BASE;

  for(i=0; i < ss->ss_num_components; i++) {
    ssc = &ss->ss_components[i];

    if(ssc->ssc_disabled)
      continue;

    if(!lav_muxer_support_stream(lm->m_config.m_type, ssc->ssc_type)) {
      tvhwarn(LS_LIBAV,  "%s is not supported in %s", 
	      streaming_component_type2txt(ssc->ssc_type), 
	      muxer_container_type2txt(lm->m_config.m_type));
      ssc->ssc_muxer_disabled = 1;
      continue;
    }

    if(lav_muxer_add_stream(lm, ssc)) {
      tvherror(LS_LIBAV,  "Failed to add %s stream", 
	       streaming_component_type2txt(ssc->ssc_type));
      ssc->ssc_muxer_disabled = 1;
      continue;
    }
  }

  if(lm->m_config.m_type == MC_AVMP4) {
    av_dict_set(&opts, "frag_duration", "1", 0);
    av_dict_set(&opts, "ism_lookahead", "0", 0);
  }

  if(!lm->lm_oc->nb_streams) {
    tvherror(LS_LIBAV,  "No supported streams available");
    lm->m_errors++;
    return -1;
  } else if(avformat_write_header(lm->lm_oc, &opts) < 0) {
    tvherror(LS_LIBAV,  "Failed to write %s header", 
	     muxer_container_type2txt(lm->m_config.m_type));
    lm->m_errors++;
    return -1;
  }

  if (opts)
    av_dict_free(&opts);

  lm->lm_init = 1;

  return 0;
}