dvb: Switch to MPEG-TS SI library

Also serves as an example of using mpegts library from a plugin

https://bugzilla.gnome.org/show_bug.cgi?id=702724
This commit is contained in:
Edward Hervey 2013-06-23 08:44:08 +02:00
parent 92edd82c86
commit 10c929c795
10 changed files with 109 additions and 169 deletions

View file

@ -18,7 +18,9 @@ libgstdvb_la_SOURCES = \
parsechannels.c
libgstdvb_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS)
libgstdvb_la_LIBADD = $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS)
libgstdvb_la_LIBADD = \
$(top_builddir)/gst-libs/gst/mpegts/libgstmpegts-$(GST_API_VERSION).la \
$(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS)
libgstdvb_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstdvb_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
@ -36,4 +38,3 @@ noinst_HEADERS = \
camapplicationinfo.h \
camconditionalaccess.h \
parsechannels.h

View file

@ -70,7 +70,7 @@ cam_conditional_access_destroy (CamConditionalAccess * cas)
}
static CamReturn
send_ca_pmt (CamConditionalAccess * cas, GstStructure * pmt,
send_ca_pmt (CamConditionalAccess * cas, GstMpegTSPMT * pmt,
guint8 list_management, guint8 cmd_id)
{
CamReturn ret;
@ -108,7 +108,7 @@ send_ca_pmt (CamConditionalAccess * cas, GstStructure * pmt,
CamReturn
cam_conditional_access_set_pmt (CamConditionalAccess * cas,
GstStructure * pmt, CamConditionalAccessPmtFlag flag)
GstMpegTSPMT * pmt, CamConditionalAccessPmtFlag flag)
{
return send_ca_pmt (cas, pmt, flag, 0x01 /* ok_descrambling */ );
}

View file

@ -50,6 +50,6 @@ CamConditionalAccess *cam_conditional_access_new (void);
void cam_conditional_access_destroy (CamConditionalAccess *cas);
CamReturn cam_conditional_access_set_pmt (CamConditionalAccess *cas,
GstStructure *pmt, CamConditionalAccessPmtFlag flag);
GstMpegTSPMT *pmt, CamConditionalAccessPmtFlag flag);
#endif /* CAM_CONDITIONAL_ACCESS_H */

View file

@ -217,7 +217,7 @@ cam_device_ready (CamDevice * device)
void
cam_device_set_pmt (CamDevice * device,
GstStructure * pmt, CamConditionalAccessPmtFlag flag)
GstMpegTSPMT * pmt, CamConditionalAccessPmtFlag flag)
{
g_return_if_fail (device != NULL);
g_return_if_fail (device->state == CAM_DEVICE_STATE_OPEN);

View file

@ -64,6 +64,6 @@ void cam_device_close (CamDevice *device);
gboolean cam_device_ready (CamDevice *device);
void cam_device_poll (CamDevice *device);
void cam_device_set_pmt (CamDevice *device,
GstStructure *pmt, CamConditionalAccessPmtFlag flag);
GstMpegTSPMT *pmt, CamConditionalAccessPmtFlag flag);
#endif /* CAM_DEVICE_H */

View file

@ -32,7 +32,6 @@
#include "camswclient.h"
#include "cam.h"
#include "camutils.h"
#define GST_CAT_DEFAULT cam_debug_cat
#define UNIX_PATH_MAX 108
@ -111,7 +110,7 @@ cam_sw_client_close (CamSwClient * client)
}
static void
send_ca_pmt (CamSwClient * client, GstStructure * pmt,
send_ca_pmt (CamSwClient * client, GstMpegTSPMT * pmt,
guint8 list_management, guint8 cmd_id)
{
guint8 *buffer;
@ -146,7 +145,7 @@ send_ca_pmt (CamSwClient * client, GstStructure * pmt,
}
void
cam_sw_client_set_pmt (CamSwClient * client, GstStructure * pmt)
cam_sw_client_set_pmt (CamSwClient * client, GstMpegTSPMT * pmt)
{
g_return_if_fail (client != NULL);
g_return_if_fail (pmt != NULL);
@ -156,7 +155,7 @@ cam_sw_client_set_pmt (CamSwClient * client, GstStructure * pmt)
}
void
cam_sw_client_update_pmt (CamSwClient * client, GstStructure * pmt)
cam_sw_client_update_pmt (CamSwClient * client, GstMpegTSPMT * pmt)
{
g_return_if_fail (client != NULL);
g_return_if_fail (pmt != NULL);

View file

@ -25,6 +25,7 @@
#define CAM_SW_CLIENT_H
#include <glib.h>
#include "camutils.h"
typedef enum
{
@ -47,7 +48,7 @@ void cam_sw_client_free (CamSwClient *sw_client);
gboolean cam_sw_client_open (CamSwClient *sw_client, const char *sock_path);
void cam_sw_client_close (CamSwClient *sw_client);
void cam_sw_client_set_pmt (CamSwClient *sw_client, GstStructure *pmt);
void cam_sw_client_update_pmt (CamSwClient *sw_client, GstStructure *pmt);
void cam_sw_client_set_pmt (CamSwClient *sw_client, GstMpegTSPMT *pmt);
void cam_sw_client_update_pmt (CamSwClient *sw_client, GstMpegTSPMT *pmt);
#endif /* CAM_SW_CLIENT_H */

View file

@ -171,42 +171,34 @@ cam_read_length_field (guint8 * buff, guint * length)
*/
static guint
get_ca_descriptors_length (GValueArray * descriptors)
get_ca_descriptors_length (GArray * descriptors)
{
guint i;
guint nb_desc = descriptors->len;
guint len = 0;
GValue *value;
GString *desc;
if (descriptors != NULL) {
for (i = 0; i < descriptors->n_values; ++i) {
value = g_value_array_get_nth (descriptors, i);
desc = (GString *) g_value_get_boxed (value);
if (desc->str[0] == 0x09)
len += desc->len;
}
for (i = 0; i < nb_desc; i++) {
GstMpegTSDescriptor *desc =
&g_array_index (descriptors, GstMpegTSDescriptor, i);
if (desc->descriptor_tag == 0x09)
len += desc->descriptor_length;
}
return len;
}
static guint8 *
write_ca_descriptors (guint8 * body, GValueArray * descriptors)
write_ca_descriptors (guint8 * body, GArray * descriptors)
{
guint i;
GValue *value;
GString *desc;
guint i, nb_desc;
if (descriptors != NULL) {
for (i = 0; i < descriptors->n_values; ++i) {
value = g_value_array_get_nth (descriptors, i);
desc = (GString *) g_value_get_boxed (value);
if (desc->str[0] == 0x09) {
memcpy (body, desc->str, desc->len);
body += desc->len;
}
nb_desc = descriptors->len;
for (i = 0; i < nb_desc; i++) {
GstMpegTSDescriptor *desc =
&g_array_index (descriptors, GstMpegTSDescriptor, i);
if (desc->descriptor_tag == 0x09) {
memcpy (body, desc->descriptor_data, desc->descriptor_length);
body += desc->descriptor_length;
}
}
@ -214,59 +206,36 @@ write_ca_descriptors (guint8 * body, GValueArray * descriptors)
}
guint8 *
cam_build_ca_pmt (GstStructure * pmt, guint8 list_management, guint8 cmd_id,
cam_build_ca_pmt (GstMpegTSPMT * pmt, guint8 list_management, guint8 cmd_id,
guint * size)
{
GstMpegTSSection *section = (GstMpegTSSection *) pmt;
guint body_size = 0;
guint8 *buffer;
guint8 *body;
GList *lengths = NULL;
guint len = 0;
const GValue *streams;
guint program_number;
guint version_number;
guint i;
const GValue *value;
GstStructure *stream;
GValueArray *program_descriptors = NULL;
GValueArray *stream_descriptors = NULL;
gst_structure_get_uint (pmt, "program-number", &program_number);
gst_structure_get_uint (pmt, "version-number", &version_number);
streams = gst_structure_get_value (pmt, "streams");
value = gst_structure_get_value (pmt, "descriptors");
if (value != NULL) {
program_descriptors = g_value_get_boxed (value);
/* get the length of program level CA_descriptor()s */
len = get_ca_descriptors_length (program_descriptors);
if (len > 0)
/* add one byte for the program level cmd_id */
len += 1;
}
/* get the length of program level CA_descriptor()s */
len = get_ca_descriptors_length (pmt->descriptors);
if (len > 0)
/* add one byte for the program level cmd_id */
len += 1;
lengths = g_list_append (lengths, GINT_TO_POINTER (len));
body_size += 6 + len;
/* get the length of stream level CA_descriptor()s */
if (streams != NULL) {
for (i = 0; i < gst_value_list_get_size (streams); ++i) {
value = gst_value_list_get_value (streams, i);
stream = g_value_get_boxed (value);
for (i = 0; i < pmt->streams->len; i++) {
GstMpegTSPMTStream *pmtstream = g_ptr_array_index (pmt->streams, i);
value = gst_structure_get_value (stream, "descriptors");
len = 0;
if (value != NULL) {
stream_descriptors = g_value_get_boxed (value);
len = get_ca_descriptors_length (pmtstream->descriptors);
if (len > 0)
/* one byte for the stream level cmd_id */
len += 1;
len = get_ca_descriptors_length (stream_descriptors);
if (len > 0)
/* one byte for the stream level cmd_id */
len += 1;
}
lengths = g_list_append (lengths, GINT_TO_POINTER (len));
body_size += 5 + len;
}
lengths = g_list_append (lengths, GINT_TO_POINTER (len));
body_size += 5 + len;
}
GST_DEBUG ("Body Size %d", body_size);
@ -278,14 +247,14 @@ cam_build_ca_pmt (GstStructure * pmt, guint8 list_management, guint8 cmd_id,
*body++ = list_management;
/* program_number 16 uimsbf */
GST_WRITE_UINT16_BE (body, program_number);
GST_WRITE_UINT16_BE (body, section->subtable_extension);
body += 2;
/* reserved 2
* version_number 5
* current_next_indicator 1
*/
*body++ = (version_number << 1) | 0x01;
*body++ = (section->version_number << 1) | 0x01;
/* Reserved 4
* program_info_length 12
@ -298,22 +267,14 @@ cam_build_ca_pmt (GstStructure * pmt, guint8 list_management, guint8 cmd_id,
if (len != 0) {
*body++ = cmd_id;
body = write_ca_descriptors (body, program_descriptors);
body = write_ca_descriptors (body, pmt->descriptors);
}
for (i = 0; i < gst_value_list_get_size (streams); ++i) {
guint stream_type;
guint stream_pid;
for (i = 0; i < pmt->streams->len; i++) {
GstMpegTSPMTStream *pmtstream = g_ptr_array_index (pmt->streams, i);
value = gst_value_list_get_value (streams, i);
stream = g_value_get_boxed (value);
gst_structure_get_uint (stream, "stream-type", &stream_type);
gst_structure_get_uint (stream, "pid", &stream_pid);
value = gst_structure_get_value (stream, "descriptors");
*body++ = stream_type;
GST_WRITE_UINT16_BE (body, stream_pid);
*body++ = pmtstream->stream_type;
GST_WRITE_UINT16_BE (body, pmtstream->pid);
body += 2;
len = GPOINTER_TO_INT (lengths->data);
lengths = g_list_delete_link (lengths, lengths);
@ -322,8 +283,7 @@ cam_build_ca_pmt (GstStructure * pmt, guint8 list_management, guint8 cmd_id,
if (len != 0) {
*body++ = cmd_id;
stream_descriptors = g_value_get_boxed (value);
body = write_ca_descriptors (body, stream_descriptors);
body = write_ca_descriptors (body, pmtstream->descriptors);
}
}

View file

@ -26,6 +26,7 @@
#include <glib.h>
#include <gst/gst.h>
#include <gst/mpegts/mpegts.h>
#define TPDU_HEADER_SIZE_INDICATOR 0x80
@ -54,6 +55,6 @@ typedef enum
guint8 cam_calc_length_field_size (guint length);
guint8 cam_write_length_field (guint8 *buff, guint length);
guint8 cam_read_length_field (guint8 *buff, guint *length);
guint8 *cam_build_ca_pmt (GstStructure *pmt, guint8 list_management, guint8 cmd_id, guint *size);
guint8 *cam_build_ca_pmt (GstMpegTSPMT *pmt, guint8 list_management, guint8 cmd_id, guint *size);
#endif /* CAM_UTILS_H */

View file

@ -27,6 +27,7 @@
#endif
#include <stdlib.h>
#include <string.h>
#include <gst/mpegts/mpegts.h>
#include "dvbbasebin.h"
#include "parsechannels.h"
@ -84,8 +85,8 @@ typedef struct
gint program_number;
guint16 pmt_pid;
guint16 pcr_pid;
GstStructure *pmt;
GstStructure *old_pmt;
GstMpegTSPMT *pmt;
GstMpegTSPMT *old_pmt;
gboolean selected;
gboolean pmt_active;
gboolean active;
@ -105,9 +106,9 @@ static GstStateChangeReturn dvb_base_bin_change_state (GstElement * element,
GstStateChange transition);
static void dvb_base_bin_handle_message (GstBin * bin, GstMessage * message);
static void dvb_base_bin_pat_info_cb (DvbBaseBin * dvbbasebin,
const GstStructure * pat);
GstMpegTSSection * pat);
static void dvb_base_bin_pmt_info_cb (DvbBaseBin * dvbbasebin,
const GstStructure * pmt);
GstMpegTSSection * pmt);
static GstPad *dvb_base_bin_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static void dvb_base_bin_release_pad (GstElement * element, GstPad * pad);
@ -540,7 +541,7 @@ dvb_base_bin_reset_pmtlist (DvbBaseBin * dvbbasebin)
{
CamConditionalAccessPmtFlag flag;
GList *walk;
GstStructure *pmt;
GstMpegTSPMT *pmt;
walk = dvbbasebin->pmtlist;
while (walk) {
@ -556,7 +557,7 @@ dvb_base_bin_reset_pmtlist (DvbBaseBin * dvbbasebin)
flag = CAM_CONDITIONAL_ACCESS_PMT_FLAG_MORE;
}
pmt = GST_STRUCTURE (walk->data);
pmt = (GstMpegTSPMT *) walk->data;
cam_device_set_pmt (dvbbasebin->hwcam, pmt, flag);
walk = walk->next;
@ -660,30 +661,18 @@ dvb_base_bin_rebuild_filter (DvbBaseBin * dvbbasebin)
}
static void
dvb_base_bin_remove_pmt_streams (DvbBaseBin * dvbbasebin, GstStructure * pmt)
dvb_base_bin_remove_pmt_streams (DvbBaseBin * dvbbasebin, GstMpegTSPMT * pmt)
{
const GValue *streams;
guint program_number;
gint i;
const GValue *value;
GstStructure *stream_info;
DvbBaseBinStream *stream;
guint pid;
guint stream_type;
gst_structure_get_uint (pmt, "program-number", &program_number);
streams = gst_structure_get_value (pmt, "streams");
for (i = 0; i < pmt->streams->len; i++) {
GstMpegTSPMTStream *pmtstream = g_ptr_array_index (pmt->streams, i);
for (i = 0; i < gst_value_list_get_size (streams); ++i) {
value = gst_value_list_get_value (streams, i);
stream_info = g_value_get_boxed (value);
gst_structure_get_uint (stream_info, "pid", &pid);
gst_structure_get_uint (stream_info, "stream-type", &stream_type);
stream = dvb_base_bin_get_stream (dvbbasebin, (guint16) pid);
stream = dvb_base_bin_get_stream (dvbbasebin, pmtstream->pid);
if (stream == NULL) {
GST_WARNING_OBJECT (dvbbasebin, "removing unknown stream %d ??", pid);
GST_WARNING_OBJECT (dvbbasebin, "removing unknown stream %d ??",
pmtstream->pid);
continue;
}
@ -692,32 +681,20 @@ dvb_base_bin_remove_pmt_streams (DvbBaseBin * dvbbasebin, GstStructure * pmt)
}
static void
dvb_base_bin_add_pmt_streams (DvbBaseBin * dvbbasebin, GstStructure * pmt)
dvb_base_bin_add_pmt_streams (DvbBaseBin * dvbbasebin, GstMpegTSPMT * pmt)
{
DvbBaseBinStream *stream;
const GValue *streams;
guint program_number;
gint i;
const GValue *value;
GstStructure *stream_info;
guint pid;
guint stream_type;
gst_structure_get_uint (pmt, "program-number", &program_number);
streams = gst_structure_get_value (pmt, "streams");
for (i = 0; i < pmt->streams->len; i++) {
GstMpegTSPMTStream *pmtstream = g_ptr_array_index (pmt->streams, i);
for (i = 0; i < gst_value_list_get_size (streams); ++i) {
value = gst_value_list_get_value (streams, i);
stream_info = g_value_get_boxed (value);
GST_DEBUG ("filtering stream %d stream_type %d", pmtstream->pid,
pmtstream->stream_type);
gst_structure_get_uint (stream_info, "pid", &pid);
gst_structure_get_uint (stream_info, "stream-type", &stream_type);
GST_DEBUG ("filtering stream %d stream_type %d", pid, stream_type);
stream = dvb_base_bin_get_stream (dvbbasebin, (guint16) pid);
stream = dvb_base_bin_get_stream (dvbbasebin, pmtstream->pid);
if (stream == NULL)
stream = dvb_base_bin_add_stream (dvbbasebin, (guint16) pid);
stream = dvb_base_bin_add_stream (dvbbasebin, pmtstream->pid);
++stream->usecount;
}
}
@ -727,7 +704,6 @@ dvb_base_bin_activate_program (DvbBaseBin * dvbbasebin,
DvbBaseBinProgram * program)
{
DvbBaseBinStream *stream;
guint pid;
if (program->old_pmt) {
dvb_base_bin_remove_pmt_streams (dvbbasebin, program->old_pmt);
@ -749,8 +725,7 @@ dvb_base_bin_activate_program (DvbBaseBin * dvbbasebin,
guint16 old_pcr_pid;
old_pcr_pid = program->pcr_pid;
gst_structure_get_uint (program->pmt, "pcr-pid", &pid);
program->pcr_pid = pid;
program->pcr_pid = program->pmt->pcr_pid;
if (old_pcr_pid != G_MAXUINT16 && old_pcr_pid != program->pcr_pid)
dvb_base_bin_get_stream (dvbbasebin, old_pcr_pid)->usecount--;
@ -800,15 +775,22 @@ dvb_base_bin_handle_message (GstBin * bin, GstMessage * message)
dvbbasebin = GST_DVB_BASE_BIN (bin);
if (message->type == GST_MESSAGE_ELEMENT &&
GST_ELEMENT (message->src) == GST_ELEMENT (dvbbasebin->tsparse)) {
const GstStructure *s = gst_message_get_structure (message);
const gchar *structure_name = gst_structure_get_name (s);
if (GST_ELEMENT (message->src) == GST_ELEMENT (dvbbasebin->tsparse)) {
GstMpegTSSection *section = gst_message_parse_mpegts_section (message);
if (strcmp (structure_name, "pat") == 0)
dvb_base_bin_pat_info_cb (dvbbasebin, s);
else if (strcmp (structure_name, "pmt") == 0)
dvb_base_bin_pmt_info_cb (dvbbasebin, s);
if (section) {
switch (GST_MPEGTS_SECTION_TYPE (section)) {
case GST_MPEGTS_SECTION_PAT:
dvb_base_bin_pat_info_cb (dvbbasebin, section);
break;
case GST_MPEGTS_SECTION_PMT:
dvb_base_bin_pmt_info_cb (dvbbasebin, section);
break;
default:
break;
}
gst_mpegts_section_unref (section);
}
}
/* chain up */
@ -818,34 +800,29 @@ dvb_base_bin_handle_message (GstBin * bin, GstMessage * message)
static void
dvb_base_bin_pat_info_cb (DvbBaseBin * dvbbasebin,
const GstStructure * pat_info)
dvb_base_bin_pat_info_cb (DvbBaseBin * dvbbasebin, GstMpegTSSection * section)
{
GArray *pat;
DvbBaseBinProgram *program;
DvbBaseBinStream *stream;
const GValue *value;
GstStructure *program_info;
guint program_number;
guint pid;
guint old_pmt_pid;
gint i;
gboolean rebuild_filter = FALSE;
const GValue *programs;
programs = gst_structure_get_value (pat_info, "programs");
for (i = 0; i < gst_value_list_get_size (programs); ++i) {
value = gst_value_list_get_value (programs, i);
program_info = g_value_get_boxed (value);
if (!(pat = gst_mpegts_section_get_pat (section))) {
GST_WARNING_OBJECT (dvbbasebin, "got invalid PAT");
return;
}
gst_structure_get_uint (program_info, "program-number", &program_number);
gst_structure_get_uint (program_info, "pid", &pid);
for (i = 0; i < pat->len; i++) {
GstMpegTSPatProgram *patp = &g_array_index (pat, GstMpegTSPatProgram, i);
program = dvb_base_bin_get_program (dvbbasebin, program_number);
program = dvb_base_bin_get_program (dvbbasebin, patp->program_number);
if (program == NULL)
program = dvb_base_bin_add_program (dvbbasebin, program_number);
program = dvb_base_bin_add_program (dvbbasebin, patp->program_number);
old_pmt_pid = program->pmt_pid;
program->pmt_pid = pid;
program->pmt_pid = patp->network_or_program_map_PID;
if (program->selected) {
/* PAT update */
@ -867,12 +844,13 @@ dvb_base_bin_pat_info_cb (DvbBaseBin * dvbbasebin,
}
static void
dvb_base_bin_pmt_info_cb (DvbBaseBin * dvbbasebin, const GstStructure * pmt)
dvb_base_bin_pmt_info_cb (DvbBaseBin * dvbbasebin, GstMpegTSSection * section)
{
GstMpegTSPMT *pmt = (GstMpegTSPMT *) section;
DvbBaseBinProgram *program;
guint program_number;
gst_structure_get_uint (pmt, "program-number", &program_number);
program_number = section->subtable_extension;
program = dvb_base_bin_get_program (dvbbasebin, program_number);
if (program == NULL) {
@ -882,7 +860,7 @@ dvb_base_bin_pmt_info_cb (DvbBaseBin * dvbbasebin, const GstStructure * pmt)
}
program->old_pmt = program->pmt;
program->pmt = gst_structure_copy (pmt);
program->pmt = (GstMpegTSPMT *) gst_mpegts_section_ref (pmt);
/* activate the program if it's selected and either it's not active or its pmt
* changed */
@ -890,7 +868,7 @@ dvb_base_bin_pmt_info_cb (DvbBaseBin * dvbbasebin, const GstStructure * pmt)
dvb_base_bin_activate_program (dvbbasebin, program);
if (program->old_pmt) {
gst_structure_free (program->old_pmt);
gst_mpegts_section_unref (program->old_pmt);
program->old_pmt = NULL;
}
}
@ -987,7 +965,7 @@ dvb_base_bin_program_destroy (gpointer data)
program = (DvbBaseBinProgram *) data;
if (program->pmt)
gst_structure_free (program->pmt);
gst_mpegts_section_unref (program->pmt);
g_free (program);
}