static void
dvb_base_bin_pat_info_cb (DvbBaseBin * dvbbasebin, GstMpegtsSection * section)
{
  GPtrArray *pat;
  DvbBaseBinProgram *program;
  DvbBaseBinStream *stream;
  guint old_pmt_pid;
  gint i;
  gboolean rebuild_filter = FALSE;

  if (!(pat = gst_mpegts_section_get_pat (section))) {
    GST_WARNING_OBJECT (dvbbasebin, "got invalid PAT");
    return;
  }

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

    program = dvb_base_bin_get_program (dvbbasebin, patp->program_number);
    if (program == NULL)
      program = dvb_base_bin_add_program (dvbbasebin, patp->program_number);

    old_pmt_pid = program->pmt_pid;
    program->pmt_pid = patp->network_or_program_map_PID;

    if (program->selected) {
      /* PAT update */
      if (old_pmt_pid != G_MAXUINT16 && old_pmt_pid != program->pmt_pid) {
        dvb_base_bin_unref_stream (dvb_base_bin_get_stream (dvbbasebin,
                old_pmt_pid));
      }

      stream = dvb_base_bin_get_stream (dvbbasebin, program->pmt_pid);
      if (stream == NULL)
        stream = dvb_base_bin_add_stream (dvbbasebin, program->pmt_pid);

      dvb_base_bin_ref_stream (stream);

      rebuild_filter = TRUE;
    }
  }
  g_ptr_array_unref (pat);

  if (rebuild_filter)
    dvb_base_bin_rebuild_filter (dvbbasebin);
}
Example #2
0
static void
dump_pat (GstMpegTsSection * section)
{
  GPtrArray *pat = gst_mpegts_section_get_pat (section);
  guint i, len;

  len = pat->len;
  g_printf ("   %d program(s):\n", len);

  for (i = 0; i < len; i++) {
    GstMpegTsPatProgram *patp = g_ptr_array_index (pat, i);

    g_print
        ("     program_number:%6d (0x%04x), network_or_program_map_PID:0x%04x\n",
        patp->program_number, patp->program_number,
        patp->network_or_program_map_PID);
  }

  g_ptr_array_unref (pat);
}
Example #3
0
static void
dump_pat (GstMpegtsSection * section, ATS_METADATA* data)
{
  GPtrArray *pat = gst_mpegts_section_get_pat (section);
  guint i, len;

  len = pat->len;
  if ((data == NULL) || (data->prog_info != NULL)) return;
  for (i = 0; i < len; i++) {
    GstMpegtsPatProgram *patp = g_ptr_array_index (pat, i);
    if (patp->program_number == 0) continue;
    ATS_CH_DATA* tmpch = g_new(ATS_CH_DATA, 1);
    tmpch->number = patp->program_number;
    tmpch->xid = 0;
    tmpch->pids_num = 0;
    tmpch->to_be_analyzed = FALSE;
    tmpch->provider_name = NULL;
    tmpch->service_name = NULL;
    data->prog_info = g_slist_append(data->prog_info, tmpch);   
  }
  g_ptr_array_unref (pat);
}
Example #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;
}