~ubuntu-branches/ubuntu/lucid/gst-plugins-bad0.10/lucid-proposed

« back to all changes in this revision

Viewing changes to gst/mpegdemux/mpegtsparse.c

  • Committer: Bazaar Package Importer
  • Author(s): Tony Espy
  • Date: 2009-12-04 13:17:51 UTC
  • mfrom: (18.4.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091204131751-hpo02yltrcsmy1xh
Tags: 0.10.17-1ubuntu1
* Merge from Debian testing (LP: #481645), remaining changes:
  - Removed plugins that are now provided -good
    - libgstdtmf.so
    - libgstvalve.so
    - libgstautoconvert.so
    - libgstrtpmux.so
    - libgstliveadder.so

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
  GstFlowReturn flow_return;
76
76
};
77
77
 
 
78
static GQuark QUARK_PROGRAMS;
 
79
static GQuark QUARK_PROGRAM_NUMBER;
 
80
static GQuark QUARK_PID;
 
81
static GQuark QUARK_PCR_PID;
 
82
static GQuark QUARK_STREAMS;
 
83
static GQuark QUARK_STREAM_TYPE;
 
84
 
78
85
static GstElementDetails mpegts_parse_details =
79
86
GST_ELEMENT_DETAILS ("MPEG transport stream parser",
80
87
    "Codec/Parser",
134
141
static GstStateChangeReturn mpegts_parse_change_state (GstElement * element,
135
142
    GstStateChange transition);
136
143
static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query);
 
144
static void _extra_init (GType type);
137
145
 
138
 
GST_BOILERPLATE (MpegTSParse, mpegts_parse, GstElement, GST_TYPE_ELEMENT);
 
146
GST_BOILERPLATE_FULL (MpegTSParse, mpegts_parse, GstElement, GST_TYPE_ELEMENT,
 
147
    _extra_init);
139
148
 
140
149
static const guint32 crc_tab[256] = {
141
150
  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
197
206
}
198
207
 
199
208
static void
 
209
_extra_init (GType type)
 
210
{
 
211
  QUARK_PROGRAMS = g_quark_from_string ("programs");
 
212
  QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number");
 
213
  QUARK_PID = g_quark_from_string ("pid");
 
214
  QUARK_PCR_PID = g_quark_from_string ("pcr-pid");
 
215
  QUARK_STREAMS = g_quark_from_string ("streams");
 
216
  QUARK_STREAM_TYPE = g_quark_from_string ("stream-type");
 
217
}
 
218
 
 
219
static void
200
220
mpegts_parse_base_init (gpointer klass)
201
221
{
202
222
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
276
296
  parse->psi_pids = g_hash_table_new (g_direct_hash, g_direct_equal);
277
297
  parse->pes_pids = g_hash_table_new (g_direct_hash, g_direct_equal);
278
298
  mpegts_parse_reset (parse);
 
299
 
279
300
}
280
301
 
281
302
static void
564
585
  const GValue *value;
565
586
 
566
587
  if (program->pmt_info) {
567
 
    streams = gst_structure_get_value (program->pmt_info, "streams");
 
588
    streams = gst_structure_id_get_value (program->pmt_info, QUARK_STREAMS);
568
589
 
569
590
    for (i = 0; i < gst_value_list_get_size (streams); ++i) {
570
591
      value = gst_value_list_get_value (streams, i);
571
592
      stream = g_value_get_boxed (value);
572
 
      gst_structure_get_uint (stream, "pid", &pid);
573
 
      gst_structure_get_uint (stream, "stream-type", &stream_type);
 
593
      gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid,
 
594
          QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL);
574
595
      mpegts_parse_program_remove_stream (parse, program, (guint16) pid);
575
596
      g_hash_table_remove (parse->pes_pids, GINT_TO_POINTER ((gint) pid));
576
597
    }
745
766
mpegts_parse_push (MpegTSParse * parse, MpegTSPacketizerPacket * packet,
746
767
    MpegTSPacketizerSection * section)
747
768
{
748
 
  GstIterator *iterator;
 
769
  guint32 pads_cookie;
749
770
  gboolean done = FALSE;
750
 
  gpointer pad = NULL;
 
771
  GstPad *pad = NULL;
751
772
  MpegTSParsePad *tspad;
752
773
  guint16 pid;
753
774
  GstBuffer *buffer;
754
775
  GstFlowReturn ret;
755
 
  GstCaps *caps;
 
776
  GList *srcpads;
756
777
 
757
778
  pid = packet->pid;
758
779
  buffer = packet->buffer;
759
780
  /* we have the same caps on all the src pads */
760
 
  caps = gst_static_pad_template_get_caps (&src_template);
761
 
  gst_buffer_set_caps (buffer, caps);
762
 
  gst_caps_unref (caps);
 
781
  gst_buffer_set_caps (buffer, parse->packetizer->caps);
763
782
 
764
783
  GST_OBJECT_LOCK (parse);
765
784
  /* clear tspad->pushed on pads */
769
788
    ret = GST_FLOW_NOT_LINKED;
770
789
  else
771
790
    ret = GST_FLOW_OK;
 
791
 
 
792
  /* Get cookie and source pads list */
 
793
  pads_cookie = GST_ELEMENT_CAST (parse)->pads_cookie;
 
794
  srcpads = GST_ELEMENT_CAST (parse)->srcpads;
 
795
  if (G_LIKELY (srcpads)) {
 
796
    pad = GST_PAD_CAST (srcpads->data);
 
797
    g_object_ref (pad);
 
798
  }
772
799
  GST_OBJECT_UNLOCK (parse);
773
800
 
774
 
  iterator = gst_element_iterate_src_pads (GST_ELEMENT_CAST (parse));
775
 
  while (!done) {
776
 
    switch (gst_iterator_next (iterator, &pad)) {
777
 
      case GST_ITERATOR_OK:
778
 
        tspad = gst_pad_get_element_private (GST_PAD (pad));
779
 
 
780
 
        /* make sure to push only once if the iterator resyncs */
781
 
        if (!tspad->pushed) {
782
 
          /* ref the buffer as gst_pad_push takes a ref but we want to reuse the
783
 
           * same buffer for next pushes */
784
 
          gst_buffer_ref (buffer);
785
 
          if (section) {
786
 
            tspad->flow_return =
787
 
                mpegts_parse_tspad_push_section (parse, tspad, section, buffer);
788
 
          } else {
789
 
            tspad->flow_return =
790
 
                mpegts_parse_tspad_push (parse, tspad, pid, buffer);
791
 
          }
792
 
          tspad->pushed = TRUE;
793
 
 
794
 
          if (GST_FLOW_IS_FATAL (tspad->flow_return)) {
795
 
            /* return the error upstream */
796
 
            ret = tspad->flow_return;
797
 
            done = TRUE;
798
 
          }
799
 
        }
800
 
 
801
 
        if (ret == GST_FLOW_NOT_LINKED)
802
 
          ret = tspad->flow_return;
803
 
 
804
 
        /* the iterator refs the pad */
805
 
        g_object_unref (GST_PAD (pad));
806
 
        break;
807
 
      case GST_ITERATOR_RESYNC:
808
 
        gst_iterator_resync (iterator);
809
 
        break;
810
 
      case GST_ITERATOR_DONE:
811
 
        done = TRUE;
812
 
        break;
813
 
      default:
814
 
        g_warning ("this should not be reached");
 
801
  while (pad && !done) {
 
802
    tspad = gst_pad_get_element_private (pad);
 
803
 
 
804
    if (G_LIKELY (!tspad->pushed)) {
 
805
      /* ref the buffer as gst_pad_push takes a ref but we want to reuse the
 
806
       * same buffer for next pushes */
 
807
      gst_buffer_ref (buffer);
 
808
      if (section) {
 
809
        tspad->flow_return =
 
810
            mpegts_parse_tspad_push_section (parse, tspad, section, buffer);
 
811
      } else {
 
812
        tspad->flow_return =
 
813
            mpegts_parse_tspad_push (parse, tspad, pid, buffer);
 
814
      }
 
815
      tspad->pushed = TRUE;
 
816
 
 
817
      if (G_UNLIKELY (GST_FLOW_IS_FATAL (tspad->flow_return))) {
 
818
        /* return the error upstream */
 
819
        ret = tspad->flow_return;
 
820
        done = TRUE;
 
821
      }
 
822
 
 
823
    }
 
824
 
 
825
    if (ret == GST_FLOW_NOT_LINKED)
 
826
      ret = tspad->flow_return;
 
827
 
 
828
    g_object_unref (pad);
 
829
 
 
830
    if (G_UNLIKELY (!done)) {
 
831
      GST_OBJECT_LOCK (parse);
 
832
      if (G_UNLIKELY (pads_cookie != GST_ELEMENT_CAST (parse)->pads_cookie)) {
 
833
        /* resync */
 
834
        GST_DEBUG ("resync");
 
835
        pads_cookie = GST_ELEMENT_CAST (parse)->pads_cookie;
 
836
        srcpads = GST_ELEMENT_CAST (parse)->srcpads;
 
837
      } else {
 
838
        GST_DEBUG ("getting next pad");
 
839
        /* Get next pad */
 
840
        srcpads = g_list_next (srcpads);
 
841
      }
 
842
 
 
843
      if (srcpads) {
 
844
        pad = GST_PAD_CAST (srcpads->data);
 
845
        g_object_ref (pad);
 
846
      } else
 
847
        done = TRUE;
 
848
      GST_OBJECT_UNLOCK (parse);
815
849
    }
816
850
  }
817
851
 
818
 
  gst_iterator_free (iterator);
819
 
 
820
852
  gst_buffer_unref (buffer);
821
853
  packet->buffer = NULL;
822
854
 
829
861
  gboolean retval = FALSE;
830
862
  guint8 table_id;
831
863
  int i;
832
 
  guint8 si_tables[] = { 0x00, 0x01, 0x02, 0x03, 0x40, 0x41, 0x42, 0x46, 0x4A,
833
 
    0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
834
 
    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
835
 
    0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
836
 
    0x72, 0x73, 0x7E, 0x7F, TABLE_ID_UNSET
 
864
  static const guint8 si_tables[] =
 
865
      { 0x00, 0x01, 0x02, 0x03, 0x40, 0x41, 0x42, 0x46, 0x4A, 0x4E, 0x4F, 0x50,
 
866
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
 
867
    0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
 
868
    0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x7E,
 
869
    0x7F, TABLE_ID_UNSET
837
870
  };
838
871
  if (g_hash_table_lookup (parse->psi_pids,
839
872
          GINT_TO_POINTER ((gint) packet->pid)) != NULL)
847
880
      table_id = *(packet->data);
848
881
      i = 0;
849
882
      while (si_tables[i] != TABLE_ID_UNSET) {
850
 
        if (si_tables[i] == table_id) {
 
883
        if (G_UNLIKELY (si_tables[i] == table_id)) {
851
884
          GST_DEBUG_OBJECT (parse, "Packet has table id 0x%x", table_id);
852
885
          retval = TRUE;
853
886
          break;
855
888
        i++;
856
889
      }
857
890
    } else {
858
 
      MpegTSPacketizerStream *stream = (MpegTSPacketizerStream *)
859
 
          g_hash_table_lookup (parse->packetizer->streams,
860
 
          GINT_TO_POINTER ((gint) packet->pid));
861
 
 
 
891
      MpegTSPacketizerStream *stream = parse->packetizer->streams[packet->pid];
862
892
      if (stream) {
863
893
        i = 0;
864
894
        GST_DEBUG_OBJECT (parse, "section table id: 0x%x",
865
895
            stream->section_table_id);
866
896
        while (si_tables[i] != TABLE_ID_UNSET) {
867
 
          if (si_tables[i] == stream->section_table_id) {
 
897
          if (G_UNLIKELY (si_tables[i] == stream->section_table_id)) {
868
898
            retval = TRUE;
869
899
            break;
870
900
          }
873
903
      }
874
904
    }
875
905
  }
 
906
 
876
907
  GST_DEBUG_OBJECT (parse, "Packet of pid 0x%x is psi: %d", packet->pid,
877
908
      retval);
878
909
  return retval;
889
920
  MpegTSParseProgram *program;
890
921
  gint i;
891
922
  const GValue *programs;
892
 
  gchar *dbg;
893
923
 
894
924
  old_pat = parse->pat;
895
925
  parse->pat = gst_structure_copy (pat_info);
896
926
 
897
 
  dbg = gst_structure_to_string (pat_info);
898
 
  GST_INFO_OBJECT (parse, "PAT %s", dbg);
899
 
  g_free (dbg);
 
927
  GST_INFO_OBJECT (parse, "PAT %" GST_PTR_FORMAT, pat_info);
900
928
 
901
929
  gst_element_post_message (GST_ELEMENT_CAST (parse),
902
930
      gst_message_new_element (GST_OBJECT (parse),
903
931
          gst_structure_copy (pat_info)));
904
932
 
905
933
  GST_OBJECT_LOCK (parse);
906
 
  programs = gst_structure_get_value (pat_info, "programs");
 
934
  programs = gst_structure_id_get_value (pat_info, QUARK_PROGRAMS);
907
935
  /* activate the new table */
908
936
  for (i = 0; i < gst_value_list_get_size (programs); ++i) {
909
937
    value = gst_value_list_get_value (programs, i);
910
938
 
911
939
    program_info = g_value_get_boxed (value);
912
 
    gst_structure_get_uint (program_info, "program-number", &program_number);
913
 
    gst_structure_get_uint (program_info, "pid", &pid);
 
940
    gst_structure_id_get (program_info, QUARK_PROGRAM_NUMBER, G_TYPE_UINT,
 
941
        &program_number, QUARK_PID, G_TYPE_UINT, &pid, NULL);
914
942
 
915
943
    program = mpegts_parse_get_program (parse, program_number);
916
944
    if (program) {
939
967
  if (old_pat) {
940
968
    /* deactivate the old table */
941
969
 
942
 
    programs = gst_structure_get_value (old_pat, "programs");
 
970
    programs = gst_structure_id_get_value (old_pat, QUARK_PROGRAMS);
943
971
    for (i = 0; i < gst_value_list_get_size (programs); ++i) {
944
972
      value = gst_value_list_get_value (programs, i);
945
973
 
946
974
      program_info = g_value_get_boxed (value);
947
 
      gst_structure_get_uint (program_info, "program-number", &program_number);
948
 
      gst_structure_get_uint (program_info, "pid", &pid);
 
975
      gst_structure_id_get (program_info,
 
976
          QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number,
 
977
          QUARK_PID, G_TYPE_UINT, &pid, NULL);
949
978
 
950
979
      program = mpegts_parse_get_program (parse, program_number);
951
980
      if (program == NULL) {
958
987
        /* the program has been referenced by the new pat, keep it */
959
988
        continue;
960
989
 
961
 
      {
962
 
        gchar *dbg = gst_structure_to_string (program_info);
963
 
 
964
 
        GST_INFO_OBJECT (parse, "PAT removing program %s", dbg);
965
 
        g_free (dbg);
966
 
      }
 
990
      GST_INFO_OBJECT (parse, "PAT removing program %" GST_PTR_FORMAT,
 
991
          program_info);
967
992
 
968
993
      if (program->active)
969
994
        parse->pads_to_remove = g_list_append (parse->pads_to_remove,
997
1022
  const GValue *new_streams;
998
1023
  const GValue *value;
999
1024
 
1000
 
  gst_structure_get_uint (pmt_info, "program-number", &program_number);
1001
 
  gst_structure_get_uint (pmt_info, "pcr-pid", &pcr_pid);
1002
 
  new_streams = gst_structure_get_value (pmt_info, "streams");
 
1025
  gst_structure_id_get (pmt_info,
 
1026
      QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number,
 
1027
      QUARK_PCR_PID, G_TYPE_UINT, &pcr_pid, NULL);
 
1028
  new_streams = gst_structure_id_get_value (pmt_info, QUARK_STREAMS);
1003
1029
 
1004
1030
  GST_OBJECT_LOCK (parse);
1005
1031
  program = mpegts_parse_get_program (parse, program_number);
1028
1054
    value = gst_value_list_get_value (new_streams, i);
1029
1055
    stream = g_value_get_boxed (value);
1030
1056
 
1031
 
    gst_structure_get_uint (stream, "pid", &pid);
1032
 
    gst_structure_get_uint (stream, "stream-type", &stream_type);
 
1057
    gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid,
 
1058
        QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL);
1033
1059
    mpegts_parse_program_add_stream (parse, program,
1034
1060
        (guint16) pid, (guint8) stream_type);
1035
1061
    g_hash_table_insert (parse->pes_pids, GINT_TO_POINTER ((gint) pid),
1038
1064
  }
1039
1065
  GST_OBJECT_UNLOCK (parse);
1040
1066
 
1041
 
  {
1042
 
    gchar *dbg = gst_structure_to_string (pmt_info);
1043
 
 
1044
 
    GST_DEBUG_OBJECT (parse, "new pmt %s", dbg);
1045
 
    g_free (dbg);
1046
 
  }
 
1067
  GST_DEBUG_OBJECT (parse, "new pmt %" GST_PTR_FORMAT, pmt_info);
1047
1068
 
1048
1069
  gst_element_post_message (GST_ELEMENT_CAST (parse),
1049
1070
      gst_message_new_element (GST_OBJECT (parse),
1083
1104
  gboolean res = TRUE;
1084
1105
  GstStructure *structure = NULL;
1085
1106
 
1086
 
  if (mpegts_parse_calc_crc32 (GST_BUFFER_DATA (section->buffer),
1087
 
          GST_BUFFER_SIZE (section->buffer)) != 0) {
 
1107
  if (G_UNLIKELY (mpegts_parse_calc_crc32 (GST_BUFFER_DATA (section->buffer),
 
1108
              GST_BUFFER_SIZE (section->buffer)) != 0)) {
1088
1109
    GST_WARNING_OBJECT (parse, "bad crc in psi pid 0x%x", section->pid);
1089
1110
    return FALSE;
1090
1111
  }
1093
1114
    case 0x00:
1094
1115
      /* PAT */
1095
1116
      structure = mpegts_packetizer_parse_pat (parse->packetizer, section);
1096
 
      if (structure)
 
1117
      if (G_LIKELY (structure))
1097
1118
        mpegts_parse_apply_pat (parse, structure);
1098
1119
      else
1099
1120
        res = FALSE;
1101
1122
      break;
1102
1123
    case 0x02:
1103
1124
      structure = mpegts_packetizer_parse_pmt (parse->packetizer, section);
1104
 
      if (structure)
 
1125
      if (G_LIKELY (structure))
1105
1126
        mpegts_parse_apply_pmt (parse, section->pid, structure);
1106
1127
      else
1107
1128
        res = FALSE;
1112
1133
    case 0x41:
1113
1134
      /* NIT, other network */
1114
1135
      structure = mpegts_packetizer_parse_nit (parse->packetizer, section);
1115
 
      if (structure)
 
1136
      if (G_LIKELY (structure))
1116
1137
        mpegts_parse_apply_nit (parse, section->pid, structure);
1117
1138
      else
1118
1139
        res = FALSE;
1121
1142
    case 0x42:
1122
1143
    case 0x46:
1123
1144
      structure = mpegts_packetizer_parse_sdt (parse->packetizer, section);
1124
 
      if (structure)
 
1145
      if (G_LIKELY (structure))
1125
1146
        mpegts_parse_apply_sdt (parse, section->pid, structure);
1126
1147
      else
1127
1148
        res = FALSE;
1163
1184
    case 0x6F:
1164
1185
      /* EIT, schedule */
1165
1186
      structure = mpegts_packetizer_parse_eit (parse->packetizer, section);
1166
 
      if (structure)
 
1187
      if (G_LIKELY (structure))
1167
1188
        mpegts_parse_apply_eit (parse, section->pid, structure);
1168
1189
      else
1169
1190
        res = FALSE;
1204
1225
  GstFlowReturn res = GST_FLOW_OK;
1205
1226
  MpegTSParse *parse;
1206
1227
  gboolean parsed;
 
1228
  MpegTSPacketizerPacketReturn pret;
1207
1229
  MpegTSPacketizer *packetizer;
1208
1230
  MpegTSPacketizerPacket packet;
1209
1231
 
1211
1233
  packetizer = parse->packetizer;
1212
1234
 
1213
1235
  mpegts_packetizer_push (parse->packetizer, buf);
1214
 
  while (mpegts_packetizer_has_packets (parse->packetizer) &&
1215
 
      !GST_FLOW_IS_FATAL (res)) {
1216
 
    /* get the next packet */
1217
 
    parsed = mpegts_packetizer_next_packet (packetizer, &packet);
1218
 
    if (!parsed)
 
1236
  while (((pret =
 
1237
              mpegts_packetizer_next_packet (parse->packetizer,
 
1238
                  &packet)) != PACKET_NEED_MORE) && !GST_FLOW_IS_FATAL (res)) {
 
1239
    if (G_UNLIKELY (pret == PACKET_BAD))
1219
1240
      /* bad header, skip the packet */
1220
1241
      goto next;
1221
1242
 
1224
1245
      MpegTSPacketizerSection section;
1225
1246
 
1226
1247
      parsed = mpegts_packetizer_push_section (packetizer, &packet, &section);
1227
 
      if (!parsed)
 
1248
      if (G_UNLIKELY (!parsed))
1228
1249
        /* bad section data */
1229
1250
        goto next;
1230
1251
 
1231
 
      if (section.complete) {
 
1252
      if (G_LIKELY (section.complete)) {
1232
1253
        /* section complete */
1233
1254
        parsed = mpegts_parse_handle_psi (parse, &section);
1234
1255
        gst_buffer_unref (section.buffer);
1235
1256
 
1236
 
        if (!parsed)
 
1257
        if (G_UNLIKELY (!parsed))
1237
1258
          /* bad PSI table */
1238
1259
          goto next;
1239
1260
      }
1314
1335
  GST_DEBUG_CATEGORY_INIT (mpegts_parse_debug, "mpegtsparse", 0,
1315
1336
      "MPEG transport stream parser");
1316
1337
 
1317
 
  mpegts_packetizer_init_debug ();
1318
1338
  gst_mpegtsdesc_init_debug ();
1319
1339
 
1320
1340
  return gst_element_register (plugin, "mpegtsparse",