Beispiel #1
0
static gboolean
mpegts_base_get_tags_from_eit (MpegTSBase * base, GstMpegtsSection * section)
{
  const GstMpegtsEIT *eit;
  guint i;
  MpegTSBaseProgram *program;

  /* Early exit if it's not from the present/following table_id */
  if (section->table_id != GST_MTS_TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_PRESENT
      && section->table_id !=
      GST_MTS_TABLE_ID_EVENT_INFORMATION_OTHER_TS_PRESENT)
    return TRUE;

  eit = gst_mpegts_section_get_eit (section);
  if (G_UNLIKELY (eit == NULL))
    return FALSE;

  program = mpegts_base_get_program (base, section->subtable_extension);

  GST_DEBUG
      ("program_id:0x%04x, table_id:0x%02x, actual_stream:%d, present_following:%d, program:%p",
      section->subtable_extension, section->table_id, eit->actual_stream,
      eit->present_following, program);

  if (program && eit->present_following) {
    for (i = 0; i < eit->events->len; i++) {
      GstMpegtsEITEvent *event = g_ptr_array_index (eit->events, i);
      const GstMpegtsDescriptor *desc;

      if (event->running_status == RUNNING_STATUS_RUNNING) {
        program->event_id = event->event_id;
        if ((desc =
                gst_mpegts_find_descriptor (event->descriptors,
                    GST_MTS_DESC_DVB_SHORT_EVENT))) {
          gchar *name;
          if (gst_mpegts_descriptor_parse_dvb_short_event (desc, NULL, &name,
                  NULL)) {
            /* FIXME : Is it correct to post an event duration as a GST_TAG_DURATION ??? */
            program->tags =
                gst_tag_list_new (GST_TAG_TITLE, name, GST_TAG_DURATION,
                event->duration * GST_SECOND, NULL);
            g_free (name);
            return TRUE;
          }
        }
      }
    }
  }

  return TRUE;
}
Beispiel #2
0
static void
mpegts_parse_reset_selected_programs (MpegTSParse2 * parse,
    gchar * program_numbers)
{
  GST_OBJECT_LOCK (parse);
  if (parse->program_numbers)
    g_free (parse->program_numbers);

  parse->program_numbers = program_numbers;

  if (*parse->program_numbers != '\0') {
    gint program_number;
    MpegTSParseProgram *program;
    gchar **progs, **walk;

    progs = g_strsplit (parse->program_numbers, ":", 0);

    walk = progs;
    while (*walk != NULL) {
      program_number = strtol (*walk, NULL, 0);
      program =
          (MpegTSParseProgram *) mpegts_base_get_program ((MpegTSBase *) parse,
          program_number);
      if (program == NULL)
        /* create the program, it will get activated once we get a PMT for it */
        program = (MpegTSParseProgram *) mpegts_base_add_program ((MpegTSBase *)
            parse, program_number, G_MAXUINT16);
      program->selected = 2;
      ++walk;
    }
    g_strfreev (progs);
  }

  g_hash_table_foreach (((MpegTSBase *) parse)->programs,
      foreach_program_activate_or_deactivate, parse);

  if (parse->pads_to_remove || parse->pads_to_add)
    parse->need_sync_program_pads = TRUE;
  GST_OBJECT_UNLOCK (parse);
}
Beispiel #3
0
static gboolean
mpegts_base_apply_pmt (MpegTSBase * base, GstMpegtsSection * section)
{
  const GstMpegtsPMT *pmt;
  MpegTSBaseProgram *program, *old_program;
  guint program_number;
  gboolean initial_program = TRUE;

  pmt = gst_mpegts_section_get_pmt (section);
  if (G_UNLIKELY (pmt == NULL)) {
    GST_ERROR ("Could not get PMT (corrupted ?)");
    return FALSE;
  }

  /* FIXME : not so sure this is valid anymore */
  if (G_UNLIKELY (base->seen_pat == FALSE)) {
    GST_WARNING ("Got pmt without pat first. Returning");
    /* remove the stream since we won't get another PMT otherwise */
    mpegts_packetizer_remove_stream (base->packetizer, section->pid);
    return TRUE;
  }

  program_number = section->subtable_extension;
  GST_DEBUG ("Applying PMT (program_number:%d, pid:0x%04x)",
      program_number, section->pid);

  /* In order for stream switching to happen properly in decodebin(2),
   * we need to first add the new pads (i.e. activate the new program)
   * before removing the old ones (i.e. deactivating the old program)
   */

  old_program = mpegts_base_get_program (base, program_number);
  if (G_UNLIKELY (old_program == NULL))
    goto no_program;

  if (G_UNLIKELY (mpegts_base_is_same_program (base, old_program, section->pid,
              pmt)))
    goto same_program;

  /* If the current program is active, this means we have a new program */
  if (old_program->active) {
    MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
    old_program = mpegts_base_steal_program (base, program_number);
    program = mpegts_base_new_program (base, program_number, section->pid);
    program->patcount = old_program->patcount;
    g_hash_table_insert (base->programs,
        GINT_TO_POINTER (program_number), program);

    /* Desactivate the old program */
    /* FIXME : THIS IS BREAKING THE STREAM SWITCHING LOGIC !
     *  */
    if (klass->can_remove_program (base, old_program)) {
      mpegts_base_deactivate_program (base, old_program);
      mpegts_base_free_program (old_program);
    }
    initial_program = FALSE;
  } else
    program = old_program;

  /* activate program */
  /* Ownership of pmt_info is given to the program */
  mpegts_base_activate_program (base, program, section->pid, section, pmt,
      initial_program);

  return TRUE;

no_program:
  {
    GST_ERROR ("Attempted to apply a PMT on a program that wasn't created");
    return TRUE;
  }

same_program:
  {
    GST_DEBUG ("Not applying identical program");
    return TRUE;
  }
}
Beispiel #4
0
static gboolean
mpegts_base_apply_pat (MpegTSBase * base, GstMpegtsSection * section)
{
  GPtrArray *pat = gst_mpegts_section_get_pat (section);
  GPtrArray *old_pat;
  MpegTSBaseProgram *program;
  gint i;

  if (G_UNLIKELY (pat == NULL))
    return FALSE;

  GST_INFO_OBJECT (base, "PAT");

  /* Applying a new PAT does two things:
   * * It adds the new programs to the list of programs this element handles
   *   and increments at the same time the number of times a program is referenced.
   *
   * * If there was a previously active PAT, It decrements the reference count
   *   of all program it used. If a program is no longer needed, it is removed.
   */

  old_pat = base->pat;
  base->pat = pat;

  GST_LOG ("Activating new Program Association Table");
  /* activate the new table */
  for (i = 0; i < pat->len; ++i) {
    GstMpegtsPatProgram *patp = g_ptr_array_index (pat, i);

    program = mpegts_base_get_program (base, patp->program_number);
    if (program) {
      /* IF the program already existed, just check if the PMT PID changed */
      if (program->pmt_pid != patp->network_or_program_map_PID) {
        if (program->pmt_pid != G_MAXUINT16) {
          /* pmt pid changed */
          /* FIXME: when this happens it may still be pmt pid of another
           * program, so setting to False may make it go through expensive
           * path in is_psi unnecessarily */
          MPEGTS_BIT_UNSET (base->known_psi, program->pmt_pid);
        }

        program->pmt_pid = patp->network_or_program_map_PID;
        if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, program->pmt_pid)))
          GST_FIXME
              ("Refcounting issue. Setting twice a PMT PID (0x%04x) as know PSI",
              program->pmt_pid);
        MPEGTS_BIT_SET (base->known_psi, patp->network_or_program_map_PID);
      }
    } else {
      /* Create a new program */
      program =
          mpegts_base_add_program (base, patp->program_number,
          patp->network_or_program_map_PID);
    }
    /* We mark this program as being referenced by one PAT */
    program->patcount += 1;
  }

  if (old_pat) {
    MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
    /* deactivate the old table */
    GST_LOG ("Deactivating old Program Association Table");

    for (i = 0; i < old_pat->len; ++i) {
      GstMpegtsPatProgram *patp = g_ptr_array_index (old_pat, i);

      program = mpegts_base_get_program (base, patp->program_number);
      if (G_UNLIKELY (program == NULL)) {
        GST_DEBUG_OBJECT (base, "broken PAT, duplicated entry for program %d",
            patp->program_number);
        continue;
      }

      if (--program->patcount > 0)
        /* the program has been referenced by the new pat, keep it */
        continue;

      GST_INFO_OBJECT (base, "PAT removing program 0x%04x 0x%04x",
          patp->program_number, patp->network_or_program_map_PID);

      if (klass->can_remove_program (base, program)) {
        mpegts_base_deactivate_program (base, program);
        mpegts_base_remove_program (base, patp->program_number);
      }
      /* FIXME: when this happens it may still be pmt pid of another
       * program, so setting to False may make it go through expensive
       * path in is_psi unnecessarily */
      if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi,
                  patp->network_or_program_map_PID))) {
        GST_FIXME
            ("Program refcounting : Setting twice a pid (0x%04x) as known PSI",
            patp->network_or_program_map_PID);
      }
      MPEGTS_BIT_SET (base->known_psi, patp->network_or_program_map_PID);
      mpegts_packetizer_remove_stream (base->packetizer,
          patp->network_or_program_map_PID);
    }

    g_ptr_array_unref (old_pat);
  }

  return TRUE;
}
Beispiel #5
0
  g_return_val_if_fail (template != NULL, NULL);
  g_return_val_if_fail (GST_IS_MPEGTS_PARSE (element), NULL);
  g_return_val_if_fail (padname != NULL, NULL);

  sscanf (padname + 8, "%d", &program_num);

  GST_DEBUG_OBJECT (element, "padname:%s, program:%d", padname, program_num);

  parse = GST_MPEGTS_PARSE (element);

  tspad = mpegts_parse_create_tspad (parse, padname);
  tspad->program_number = program_num;

  /* Find if the program is already active */
  parseprogram =
      (MpegTSParseProgram *) mpegts_base_get_program (GST_MPEGTS_BASE (parse),
      program_num);
  if (parseprogram) {
    tspad->program = parseprogram;
    parseprogram->tspad = tspad;
  }

  pad = tspad->pad;
  parse->srcpads = g_list_append (parse->srcpads, pad);
  base->push_data = TRUE;
  base->push_section = TRUE;

  gst_pad_set_active (pad, TRUE);

  stream_id = gst_pad_create_stream_id (pad, element, padname + 8);

  event =