tsparse: Fix per-program-pad pushing
authorEdward Hervey <edward@centricular.com>
Fri, 19 Feb 2016 16:48:55 +0000 (17:48 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Fri, 19 Feb 2016 17:12:59 +0000 (18:12 +0100)
This fixes a couple of issues regarding the output of (request)
per-program pads output:

We would never push out PAT sections (ok, that was one reallly stupid
mistake. I guess nobody ever uses this feature ...).

In the case where the PMT section of a program was bigger than one
packet, we would only end up pushing the last packet of that PMT. Which
obviously results in the resulting stream never containing the proper
(complete) PMT.

The problem was that the program is only started (in the base class)
after the PMT section is completely parsed. When dealing with single-program
pads, tsparse only wants to push the PMT corresponding to the requested
program (and not the other ones). tsparse did that check by looking
at the streams of the program...
... but that program doesn't exist for the first packets of the initial
PMT.

The fix is to use the base class program information (if it parsed the
PAT it already has some information, like the PMT PID for a given program)
if the program hasn't started yet.

gst/mpegtsdemux/mpegtsparse.c

index 8e932d311ee8b7ca7f353ae81ac545aed3311fda..6ab2e7d17b703a2c91698c94c3eebfaf30af68cd 100644 (file)
@@ -543,9 +543,10 @@ mpegts_parse_tspad_push_section (MpegTSParse2 * parse, MpegTSParsePad * tspad,
         if (section->subtable_extension != tspad->program_number)
           to_push = FALSE;
       }
-    } else {
+    } else if (section->table_id != 0x00) {
       /* there's a program filter on the pad but the PMT for the program has not
-       * been parsed yet, ignore the pad until we get a PMT */
+       * been parsed yet, ignore the pad until we get a PMT.
+       * But we always allow PAT to go through */
       to_push = FALSE;
     }
   }
@@ -560,8 +561,10 @@ mpegts_parse_tspad_push_section (MpegTSParse2 * parse, MpegTSParsePad * tspad,
     gst_buffer_fill (buf, 0, packet->data_start,
         packet->data_end - packet->data_start);
     ret = gst_pad_push (tspad->pad, buf);
+    ret = gst_flow_combiner_update_flow (parse->flowcombiner, ret);
   }
 
+  GST_LOG_OBJECT (parse, "Returning %s", gst_flow_get_name (ret));
   return ret;
 }
 
@@ -570,29 +573,30 @@ mpegts_parse_tspad_push (MpegTSParse2 * parse, MpegTSParsePad * tspad,
     MpegTSPacketizerPacket * packet)
 {
   GstFlowReturn ret = GST_FLOW_OK;
-  MpegTSBaseStream **pad_pids = NULL;
+  MpegTSBaseProgram *bp = NULL;
 
   if (tspad->program_number != -1) {
-    if (tspad->program) {
-      MpegTSBaseProgram *bp = (MpegTSBaseProgram *) tspad->program;
-      pad_pids = bp->streams;
-    } else {
-      /* there's a program filter on the pad but the PMT for the program has not
-       * been parsed yet, ignore the pad until we get a PMT */
-      goto out;
-    }
+    if (tspad->program)
+      bp = (MpegTSBaseProgram *) tspad->program;
+    else
+      bp = mpegts_base_get_program ((MpegTSBase *) parse,
+          tspad->program_number);
   }
 
-  if (pad_pids == NULL || pad_pids[packet->pid]) {
-    GstBuffer *buf =
-        gst_buffer_new_and_alloc (packet->data_end - packet->data_start);
-    gst_buffer_fill (buf, 0, packet->data_start,
-        packet->data_end - packet->data_start);
-    /* push if there's no filter or if the pid is in the filter */
-    ret = gst_pad_push (tspad->pad, buf);
+  if (bp) {
+    if (packet->pid == bp->pmt_pid || bp->streams == NULL
+        || bp->streams[packet->pid]) {
+      GstBuffer *buf =
+          gst_buffer_new_and_alloc (packet->data_end - packet->data_start);
+      gst_buffer_fill (buf, 0, packet->data_start,
+          packet->data_end - packet->data_start);
+      /* push if there's no filter or if the pid is in the filter */
+      ret = gst_pad_push (tspad->pad, buf);
+      ret = gst_flow_combiner_update_flow (parse->flowcombiner, ret);
+    }
   }
+  GST_DEBUG_OBJECT (parse, "Returning %s", gst_flow_get_name (ret));
 
-out:
   return ret;
 }