From 719027139e9e5327399c276b531445153f274dc3 Mon Sep 17 00:00:00 2001
From: Changtao Hu <changtao.hu@mediatek.com>
Date: Thu, 22 Jun 2017 09:05:36 +0800
Subject: [PATCH] gstreamer upgrade: ogg bugs

Make patch for gstreamer upgrade
Test: OK

Signed-off-by: Changtao Hu <changtao.hu@mediatek.com>
CR-Id: AUTO00005189
---
 ext/ogg/gstoggdemux.c  | 62 ++++++++++++++++++++++++++++++++++++++++++++------
 ext/ogg/gstoggstream.c | 19 ++++++++++++++--
 ext/ogg/gstoggstream.h |  2 ++
 3 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c
index 10c34a8..15356fb 100644
--- a/ext/ogg/gstoggdemux.c
+++ b/ext/ogg/gstoggdemux.c
@@ -49,6 +49,8 @@
 
 /* we hope we get a granpos within this many bytes off the end */
 #define DURATION_CHUNK_OFFSET (64*1024)
+/*search max page count*/
+#define SEARCH_MAX_PAGE   75
 
 /* An Ogg page can not be larger than 255 segments of 255 bytes, plus
    26 bytes of header */
@@ -191,7 +193,9 @@ gst_ogg_pad_init (GstOggPad * pad)
 
   pad->map.granulerate_n = 0;
   pad->map.granulerate_d = 0;
-  pad->map.granuleshift = -1;
+  pad->map.granuleshift = 0;
+  pad->map.channel = 0;
+  pad->map.bitspersample = 0;
 }
 
 static void
@@ -813,7 +817,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
   if (!packet->b_o_s || push_headers) {
     if (pad->last_ret == GST_FLOW_OK) {
       GST_LOG_OBJECT (ogg, "Pushing buf %" GST_PTR_FORMAT, buf);
-      ret = gst_pad_push (GST_PAD_CAST (pad), buf);
+      if (gst_buffer_get_size (buf) > 0)
+        ret = gst_pad_push (GST_PAD_CAST (pad), buf);
     } else {
       GST_DEBUG_OBJECT (ogg, "not pushing buffer on error pad");
       ret = pad->last_ret;
@@ -2682,6 +2687,7 @@ gst_ogg_demux_get_prev_page (GstOggDemux * ogg, ogg_page * og, gint64 * offset)
   gint64 begin = ogg->offset;
   gint64 end = begin;
   gint64 cur_offset = -1;
+  gint hit_limit_cnt = 0;
 
   GST_LOG_OBJECT (ogg, "getting page before %" G_GINT64_FORMAT, begin);
 
@@ -2712,7 +2718,12 @@ gst_ogg_demux_get_prev_page (GstOggDemux * ogg, ogg_page * og, gint64 * offset)
       ret = gst_ogg_demux_get_next_page (ogg, og, boundary, &new_offset);
       /* we hit the upper limit, offset contains the last page start */
       if (ret == GST_FLOW_LIMIT) {
-        GST_LOG_OBJECT (ogg, "hit limit");
+        hit_limit_cnt++;
+        GST_INFO_OBJECT (ogg, "hit limit, cnt=%d", hit_limit_cnt);
+        if (hit_limit_cnt >= 3){
+          ret = GST_FLOW_OK;
+          goto beach;
+        }
         break;
       }
       /* something went wrong */
@@ -2899,8 +2910,12 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
     gst_ogg_pad_mark_discont (pad);
     pad->last_ret = GST_FLOW_OK;
 
+    GST_DEBUG_OBJECT (ogg,
+          "serialno %08x time %" GST_TIME_FORMAT,
+          pad->map.serialno, GST_TIME_ARGS (pad->start_time));
+
     if (pad->map.is_skeleton || pad->map.is_cmml || pad->added
-        || !pad->map.caps)
+        || !pad->map.caps || (pad->start_time == GST_CLOCK_TIME_NONE))
       continue;
 
     GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
@@ -4003,6 +4018,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
   gint64 offset = ogg->offset;
   ogg_page og;
   gboolean done;
+  gint loop_page_cnt = 0;
   gint i;
 
   GST_LOG_OBJECT (ogg, "reading chain at %" G_GINT64_FORMAT, offset);
@@ -4114,7 +4130,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
       if (!pad->map.is_sparse)
         done &= (pad->start_time != GST_CLOCK_TIME_NONE);
 
-      GST_LOG_OBJECT (ogg, "done %08x now %d", pad->map.serialno, done);
+      GST_LOG_OBJECT (ogg, "done %08x now %d time %" GST_TIME_FORMAT, pad->map.serialno, done, GST_TIME_ARGS (pad->start_time));
     }
 
     /* we read a page not belonging to the current chain: seek back to the
@@ -4126,8 +4142,14 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
       break;
     }
 
+    if ((loop_page_cnt >= SEARCH_MAX_PAGE) && (done == FALSE)) {
+      done = TRUE;
+      GST_ERROR_OBJECT (ogg, "(loop_page_cnt >= SEARCH_MAX_PAGE) && (done == FALSE)");
+      break;
+    }
     if (!done) {
       ret = gst_ogg_demux_get_next_page (ogg, &og, -1, NULL);
+      loop_page_cnt++;
       if (ret != GST_FLOW_OK)
         break;
     }
@@ -4154,6 +4176,7 @@ gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain)
   gboolean done = FALSE;
   ogg_page og;
   gint i;
+  gint hit_limit_count = 0;
 
   while (!done) {
     begin -= ogg->chunk_size;
@@ -4168,8 +4191,14 @@ gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain)
     while (ogg->offset < end) {
       ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, NULL);
 
-      if (ret == GST_FLOW_LIMIT)
+      if (ret == GST_FLOW_LIMIT) {
+        hit_limit_count++;
+        GST_INFO_OBJECT (ogg, "hit_limit_count=%d", hit_limit_count);
+        if (hit_limit_count >= 3) {
+          done = TRUE;
+        }
         break;
+      }
       if (ret != GST_FLOW_OK)
         return ret;
 
@@ -4313,6 +4342,12 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
   GstOggChain *chain;
   GstFlowReturn ret;
 
+  /*init og header and body*/
+  og.header_len = 0;
+  og.body_len = 0;
+  og.header = NULL;
+  og.body = NULL;
+
   /* get peer to figure out length */
   if ((peer = gst_pad_get_peer (ogg->sinkpad)) == NULL)
     goto no_peer;
@@ -4344,7 +4379,20 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
   if (ret != GST_FLOW_OK)
     goto no_last_page;
 
-  serialno = ogg_page_serialno (&og);
+  GST_DEBUG_OBJECT (ogg, "ogg_page_serialno,og.header_len=%d,og.body_len=%d",og.header_len,og.body_len);
+  if ((og.header_len > 27) && (og.header_len <= (27 + 255))) {
+    serialno = ogg_page_serialno (&og);
+  }
+  else {
+    gint i;
+    for (i = 0; i < chain->streams->len; i++) {
+      GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
+      if (pad != NULL) {
+        serialno = pad->map.serialno;
+        break;
+      }
+    }
+  } 
 
   if (!gst_ogg_chain_has_stream (chain, serialno)) {
     /* the last page is not in the first stream, this means we should
diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c
index 8426e46..e332156 100644
--- a/ext/ogg/gstoggstream.c
+++ b/ext/ogg/gstoggstream.c
@@ -28,6 +28,7 @@
 
 #include <gst/riff/riff-media.h>
 #include <gst/pbutils/pbutils.h>
+#include <gst/audio/audio.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -1599,16 +1600,30 @@ setup_ogmaudio_mapper (GstOggStream * pad, ogg_packet * packet)
   GST_DEBUG ("fourcc: %s", fstr);
 
   /* FIXME: Need to do something with the reorder map */
+  gchar *pchar=NULL;
+  guint16 n_fourcc=strtol((const char *)fstr,&pchar,16);
+
+  pad->channel = GST_READ_UINT16_LE (data + 45);
+  pad->bitspersample = GST_READ_UINT32_LE (data + 41);
   pad->caps =
-      gst_riff_create_audio_caps (fourcc, NULL, NULL, NULL, NULL, NULL, NULL);
+      gst_riff_create_audio_caps (n_fourcc, NULL, NULL, NULL, NULL, NULL, NULL);
 
-  GST_LOG ("sample rate: %d", pad->granulerate_n);
+  GST_LOG ("sample rate: %d,pad->channel: %d", pad->granulerate_n, pad->channel);
   if (pad->granulerate_n == 0)
     return FALSE;
 
   if (pad->caps) {
     gst_caps_set_simple (pad->caps,
         "rate", G_TYPE_INT, pad->granulerate_n, NULL);
+    gst_caps_set_simple (pad->caps,
+        "channels", G_TYPE_INT, pad->channel, NULL);
+    if (GST_RIFF_WAVE_FORMAT_PCM == n_fourcc) {
+      GstAudioFormat format;
+      gint wd = GST_ROUND_UP_8 (pad->bitspersample);
+      format = gst_audio_format_build_integer (wd != 8, G_LITTLE_ENDIAN, wd, wd);
+      gst_caps_set_simple (pad->caps,
+        "format", G_TYPE_STRING, gst_audio_format_to_string (format), NULL);
+    }
   } else {
     pad->caps = gst_caps_new_simple ("audio/x-ogm-unknown",
         "fourcc", G_TYPE_STRING, fstr,
diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h
index d49527f..2822a93 100644
--- a/ext/ogg/gstoggstream.h
+++ b/ext/ogg/gstoggstream.h
@@ -111,6 +111,8 @@ struct _GstOggStream
   GstOggIndex *index;
   guint64 kp_denom;
   guint64 idx_bitrate;
+  guint16 channel;
+  guint32 bitspersample;
 };
 
 
-- 
1.9.1