static void mpegts_parse_reset (MpegTSBase * base) { MpegTSParse2 *parse = (MpegTSParse2 *) base; /* Set the various know PIDs we are interested in */ /* CAT */ MPEGTS_BIT_SET (base->known_psi, 1); /* NIT, ST */ MPEGTS_BIT_SET (base->known_psi, 0x10); /* SDT, BAT, ST */ MPEGTS_BIT_SET (base->known_psi, 0x11); /* EIT, ST, CIT (TS 102 323) */ MPEGTS_BIT_SET (base->known_psi, 0x12); /* RST, ST */ MPEGTS_BIT_SET (base->known_psi, 0x13); /* RNT (TS 102 323) */ MPEGTS_BIT_SET (base->known_psi, 0x16); /* inband signalling */ MPEGTS_BIT_SET (base->known_psi, 0x1c); /* measurement */ MPEGTS_BIT_SET (base->known_psi, 0x1d); /* DIT */ MPEGTS_BIT_SET (base->known_psi, 0x1e); /* SIT */ MPEGTS_BIT_SET (base->known_psi, 0x1f); parse->first = TRUE; parse->have_group_id = FALSE; parse->group_id = G_MAXUINT; g_list_free_full (parse->pending_buffers, (GDestroyNotify) gst_buffer_unref); parse->pending_buffers = NULL; parse->current_pcr = GST_CLOCK_TIME_NONE; parse->previous_pcr = GST_CLOCK_TIME_NONE; parse->bytes_since_pcr = 0; parse->pcr_pid = parse->user_pcr_pid; }
static void mpegts_base_reset (MpegTSBase * base) { MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); mpegts_packetizer_clear (base->packetizer); memset (base->is_pes, 0, 1024); memset (base->known_psi, 0, 1024); /* FIXME : Actually these are not *always* know SI streams * depending on the variant of mpeg-ts being used. */ /* Known PIDs : PAT, TSDT, IPMP CIT */ MPEGTS_BIT_SET (base->known_psi, 0); MPEGTS_BIT_SET (base->known_psi, 2); MPEGTS_BIT_SET (base->known_psi, 3); /* TDT, TOT, ST */ MPEGTS_BIT_SET (base->known_psi, 0x14); /* network synchronization */ MPEGTS_BIT_SET (base->known_psi, 0x15); /* ATSC */ MPEGTS_BIT_SET (base->known_psi, 0x1ffb); /* FIXME : Commenting the Following lines is to be in sync with the following * commit * * 61a885613316ce7657c36a6cd215b43f9dc67b79 * mpegtsparse: don't free PAT structure which may still be needed later */ /* if (base->pat != NULL) */ /* gst_structure_free (base->pat); */ /* base->pat = NULL; */ /* pmt pids will be added and removed dynamically */ gst_segment_init (&base->segment, GST_FORMAT_UNDEFINED); base->last_seek_seqnum = (guint32) - 1; base->mode = BASE_MODE_STREAMING; base->seen_pat = FALSE; base->seek_offset = -1; base->upstream_live = FALSE; base->queried_latency = FALSE; g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program, base); if (klass->reset) klass->reset (base); }
static gboolean mpegts_base_parse_atsc_mgt (MpegTSBase * base, GstMpegtsSection * section) { const GstMpegtsAtscMGT *mgt; gint i; mgt = gst_mpegts_section_get_atsc_mgt (section); if (G_UNLIKELY (mgt == NULL)) return FALSE; for (i = 0; i < mgt->tables->len; ++i) { GstMpegtsAtscMGTTable *table = g_ptr_array_index (mgt->tables, i); if ((table->table_type >= GST_MPEGTS_ATSC_MGT_TABLE_TYPE_EIT0 && table->table_type <= GST_MPEGTS_ATSC_MGT_TABLE_TYPE_EIT127) || (table->table_type >= GST_MPEGTS_ATSC_MGT_TABLE_TYPE_ETT0 && table->table_type <= GST_MPEGTS_ATSC_MGT_TABLE_TYPE_ETT127)) { MPEGTS_BIT_SET (base->known_psi, table->pid); } } return TRUE; }
MpegTSBaseProgram * mpegts_base_add_program (MpegTSBase * base, gint program_number, guint16 pmt_pid) { MpegTSBaseProgram *program; GST_DEBUG_OBJECT (base, "program_number : %d, pmt_pid : %d", program_number, pmt_pid); program = mpegts_base_new_program (base, program_number, pmt_pid); /* Mark the PMT PID as being a known PSI PID */ if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, pmt_pid))) { GST_FIXME ("Refcounting. Setting twice a PID (0x%04x) as known PSI", pmt_pid); } MPEGTS_BIT_SET (base->known_psi, pmt_pid); g_hash_table_insert (base->programs, GINT_TO_POINTER (program_number), program); return program; }
static void mpegts_base_reset (MpegTSBase * base) { MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); mpegts_packetizer_clear (base->packetizer); memset (base->is_pes, 0, 1024); memset (base->known_psi, 0, 1024); /* FIXME : Actually these are not *always* know SI streams * depending on the variant of mpeg-ts being used. */ /* Known PIDs : PAT, TSDT, IPMP CIT */ MPEGTS_BIT_SET (base->known_psi, 0); MPEGTS_BIT_SET (base->known_psi, 2); MPEGTS_BIT_SET (base->known_psi, 3); /* TDT, TOT, ST */ MPEGTS_BIT_SET (base->known_psi, 0x14); /* network synchronization */ MPEGTS_BIT_SET (base->known_psi, 0x15); /* ATSC */ MPEGTS_BIT_SET (base->known_psi, 0x1ffb); if (base->pat) { g_ptr_array_unref (base->pat); base->pat = NULL; } gst_segment_init (&base->segment, GST_FORMAT_UNDEFINED); base->last_seek_seqnum = (guint32) - 1; base->mode = BASE_MODE_STREAMING; base->seen_pat = FALSE; base->seek_offset = -1; base->upstream_live = FALSE; base->queried_latency = FALSE; g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program, base); if (klass->reset) klass->reset (base); }
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; }
static void mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program, guint16 pmt_pid, GstMpegtsSection * section, const GstMpegtsPMT * pmt, gboolean initial_program) { guint i; MpegTSBaseClass *klass; if (G_UNLIKELY (program->active)) return; GST_DEBUG ("Activating program %d", program->program_number); /* activate new pmt */ if (program->section) gst_mpegts_section_unref (program->section); program->section = gst_mpegts_section_ref (section); program->pmt = pmt; program->pmt_pid = pmt_pid; program->pcr_pid = pmt->pcr_pid; /* extract top-level registration_id if present */ program->registration_id = get_registration_from_descriptors (pmt->descriptors); GST_DEBUG ("program 0x%04x, registration_id %" SAFE_FOURCC_FORMAT, program->program_number, SAFE_FOURCC_ARGS (program->registration_id)); for (i = 0; i < pmt->streams->len; ++i) { GstMpegtsPMTStream *stream = g_ptr_array_index (pmt->streams, i); switch (stream->stream_type) { case GST_MPEGTS_STREAM_TYPE_SCTE_DSMCC_DCB: case GST_MPEGTS_STREAM_TYPE_SCTE_SIGNALING: { guint32 registration_id = get_registration_from_descriptors (stream->descriptors); /* Not a private section stream */ if (registration_id != DRF_ID_CUEI && registration_id != DRF_ID_ETV1) break; /* Fall through on purpose - remove this PID from known_psi */ } case GST_MPEGTS_STREAM_TYPE_PRIVATE_SECTIONS: case GST_MPEGTS_STREAM_TYPE_MHEG: case GST_MPEGTS_STREAM_TYPE_DSM_CC: case GST_MPEGTS_STREAM_TYPE_DSMCC_A: case GST_MPEGTS_STREAM_TYPE_DSMCC_B: case GST_MPEGTS_STREAM_TYPE_DSMCC_C: case GST_MPEGTS_STREAM_TYPE_DSMCC_D: case GST_MPEGTS_STREAM_TYPE_SL_FLEXMUX_SECTIONS: case GST_MPEGTS_STREAM_TYPE_METADATA_SECTIONS: /* Set known PSI streams */ if (base->parse_private_sections) MPEGTS_BIT_SET (base->known_psi, stream->pid); break; default: if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->is_pes, stream->pid))) GST_FIXME ("Refcounting issue. Setting twice a PID (0x%04x) as known PES", stream->pid); if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, stream->pid))) { GST_FIXME ("Refcounting issue. Setting a known PSI PID (0x%04x) as known PES", stream->pid); MPEGTS_BIT_UNSET (base->known_psi, stream->pid); } MPEGTS_BIT_SET (base->is_pes, stream->pid); break; } mpegts_base_program_add_stream (base, program, stream->pid, stream->stream_type, stream); } /* We add the PCR pid last. If that PID is already used by one of the media * streams above, no new stream will be created */ mpegts_base_program_add_stream (base, program, pmt->pcr_pid, -1, NULL); MPEGTS_BIT_SET (base->is_pes, pmt->pcr_pid); program->active = TRUE; program->initial_program = initial_program; klass = GST_MPEGTS_BASE_GET_CLASS (base); if (klass->program_started != NULL) klass->program_started (base, program); GST_DEBUG_OBJECT (base, "new pmt activated"); }