headers prepended during raw to ADTS
conversion */
+#ifdef GST_EXT_AACPARSE_MODIFICATION /* to get more accurate duration */
+#define AAC_MAX_ESTIMATE_DURATION_BUF (1024 * 1024) /* use first 1 Mbyte */
+#define AAC_SAMPLE_PER_FRAME 1024
+
+#define AAC_MAX_PULL_RANGE_BUF (1 * 1024 * 1024) /* 1 MByte */
+#define AAC_LARGE_FILE_SIZE (2 * 1024 * 1024) /* 2 MByte */
+#define gst_aac_parse_parent_class parent_class
+#endif
+
#define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
static const gint loas_sample_rate_table[32] = {
static GstFlowReturn gst_aac_parse_pre_push_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+static guint gst_aac_parse_adts_get_fast_frame_len (const guint8 * data);
+static gboolean gst_aac_parse_src_eventfunc(GstBaseParse * parse,
+ GstEvent * event);
+/* make full aac(adts) index table when seek */
+static gboolean gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse,
+ GstEvent * event);
+int get_aac_parse_get_adts_frame_length (const unsigned char* data,
+ gint64 offset);
+static gboolean gst_aac_parse_estimate_duration (GstBaseParse * parse);
+#endif
+
G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE);
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+static inline gint
+gst_aac_parse_get_sample_rate_from_index (guint sr_idx)
+{
+ static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
+ 32000, 24000, 22050, 16000, 12000, 11025, 8000
+ };
+
+ if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
+ return aac_sample_rates[sr_idx];
+ GST_WARNING ("Invalid sample rate index %u", sr_idx);
+ return 0;
+}
+#endif
/**
* gst_aac_parse_class_init:
* @klass: #GstAacParseClass.
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_handle_frame);
parse_class->pre_push_frame =
GST_DEBUG_FUNCPTR (gst_aac_parse_pre_push_frame);
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+ /* make full aac(adts) index table when seek */
+ parse_class->src_event = GST_DEBUG_FUNCPTR (gst_aac_parse_src_eventfunc);
+#endif
}
GST_DEBUG ("initialized");
GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (aacparse));
GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (aacparse));
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+ /* to get more correct duration */
+ aacparse->first_frame = TRUE;
+#endif
}
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
}
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+ if (aacparse->first_frame == TRUE) {
+ gboolean ret = FALSE;
+ aacparse->first_frame = FALSE;
+
+ ret = gst_aac_parse_estimate_duration(parse);
+ if (!ret) {
+ GST_WARNING_OBJECT (aacparse, "can not estimate total duration");
+ ret = GST_FLOW_NOT_SUPPORTED;
+ }
+ }
+#endif
} else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
gboolean setcaps = FALSE;
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
}
}
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+ else if(aacparse->header_type == DSPAAC_HEADER_ADIF)
+ {
+ /* to get more correct duration */
+ int file_size = 0;
+ float estimated_duration = 0;
+ gint64 total_file_size;
+ gst_base_parse_get_upstream_size(parse, &total_file_size);
+ estimated_duration = ((total_file_size * 8) / (float)(aacparse->bitrate * 1000))* GST_SECOND;
+ gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration * 1000, 0);
+ }
+#endif
if (aacparse->header_type == DSPAAC_HEADER_NONE
&& aacparse->output_header_type == DSPAAC_HEADER_ADTS) {
return res;
}
+
+#ifdef GST_EXT_AACPARSE_MODIFICATION
+/**
+ * get_aac_parse_get_adts_framelength:
+ * @data: #GstBufferData.
+ * @offset: #GstBufferData offset
+ *
+ * Implementation to get adts framelength by using first some frame.
+ *
+ * Returns: frame size
+ */
+int get_aac_parse_get_adts_frame_length (const unsigned char* data,
+ gint64 offset)
+{
+ const gint adts_header_length_no_crc = 7;
+ const gint adts_header_length_with_crc = 9;
+ gint frame_size = 0;
+ gint protection_absent;
+ gint head_size;
+
+ /* check of syncword */
+ if ((data[offset+0] != 0xff) || ((data[offset+1] & 0xf6) != 0xf0)) {
+ GST_ERROR("check sync word is fail\n");
+ return -1;
+ }
+
+ /* check of protection absent */
+ protection_absent = (data[offset+1] & 0x01);
+
+ /*check of frame length */
+ frame_size = (data[offset+3] & 0x3) << 11 | data[offset+4] << 3 | data[offset+5] >> 5;
+
+ /* check of header size */
+ /* protectionAbsent is 0 if there is CRC */
+ head_size = protection_absent ? adts_header_length_no_crc : adts_header_length_with_crc;
+ if (head_size > frame_size) {
+ GST_ERROR("return frame length as 0 (frameSize %u < headSize %u)", frame_size, head_size);
+ return 0;
+ }
+
+ return frame_size;
+}
+
+/**
+ * gst_aac_parse_estimate_duration:
+ * @parse: #GstBaseParse.
+ *
+ * Implementation to get estimated total duration by using first some frame.
+ *
+ * Returns: TRUE if we can get estimated total duraion
+ */
+static gboolean
+gst_aac_parse_estimate_duration (GstBaseParse * parse)
+{
+ GstFlowReturn res = GST_FLOW_OK;
+ gint64 pull_size = 0, file_size = 0, offset = 0, num_frames=0, duration=0;
+ guint profile = 0, sample_rate_index = 0, sample_rate = 0, channel = 0;
+ guint frame_size = 0, frame_duration_us = 0, estimated_bitrate = 0;
+ guint lost_sync_count=0;
+ GstClockTime estimated_duration = GST_CLOCK_TIME_NONE;
+ GstBuffer *buffer = NULL;
+ guint8 *buf = NULL;
+ gint i = 0;
+ GstPadMode pad_mode = GST_PAD_MODE_NONE;
+ GstAacParse *aacparse;
+ gint64 buffer_size = 0;
+
+ aacparse = GST_AAC_PARSE (parse);
+ GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
+
+ /* check baseparse define these fuction */
+ gst_base_parse_get_pad_mode(parse, &pad_mode);
+ if (pad_mode != GST_PAD_MODE_PULL) {
+ GST_INFO_OBJECT (aacparse, "aac parser is not pull mode. can not estimate duration");
+ return FALSE;
+ }
+
+ gst_base_parse_get_upstream_size (parse, &file_size);
+
+ if (file_size < ADIF_MAX_SIZE) {
+ GST_ERROR_OBJECT (aacparse, "file size is too short");
+ return FALSE;
+ }
+
+ pull_size = MIN(file_size, AAC_MAX_ESTIMATE_DURATION_BUF);
+
+ res = gst_pad_pull_range (parse->sinkpad, 0, pull_size, &buffer);
+ if (res != GST_FLOW_OK) {
+ GST_ERROR_OBJECT (aacparse, "gst_pad_pull_range failed!");
+ return FALSE;
+ }
+
+ GstMapInfo map;
+ gst_buffer_map(buffer, &map, GST_MAP_READ);
+ buf = map.data;
+ buffer_size = map.size;
+ if(buffer_size != pull_size)
+ {
+ GST_ERROR_OBJECT(aacparse, "We got different buffer_size(%d) with pull_size(%d).",
+ buffer_size, pull_size);
+ }
+
+ /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
+ for (i = 0; i < buffer_size; i ++) {
+ if ((buf[i] == 0xff) && ((buf[i+1] & 0xf6) == 0xf0)) { /* aac sync word */
+ profile = (buf[i+2] >> 6) & 0x3;
+ sample_rate_index = (buf[i+2] >> 2) & 0xf;
+ sample_rate = gst_aac_parse_get_sample_rate_from_index(sample_rate_index);
+ if (sample_rate == 0) {
+ gst_buffer_unmap(buffer, &map);
+ GST_WARNING_OBJECT (aacparse, "Invalid sample rate index (0)");
+ return FALSE;
+ }
+ channel = (buf[i+2] & 0x1) << 2 | (buf[i+3] >> 6);
+
+ GST_INFO_OBJECT (aacparse, "found sync. aac fs=%d, ch=%d", sample_rate, channel);
+
+ /* count number of frames */
+ /*MODIFICATION : add defence codes for real buffer_size is different with pull_size*/
+ //while (offset < pull_size) {
+ while (offset < buffer_size) {
+ frame_size = get_aac_parse_get_adts_frame_length(buf, i + offset);
+ if (frame_size == 0) {
+ GST_ERROR_OBJECT (aacparse, "framesize error at offset %"G_GINT64_FORMAT, offset);
+ break;
+ } else if (frame_size == -1) {
+ offset++;
+ lost_sync_count++; // lost sync count limmitation 2K Bytes
+ if (lost_sync_count > (1024*2))
+ {
+ gst_buffer_unmap(buffer, &map);
+ return FALSE;
+ }
+ } else {
+ offset += frame_size;
+ num_frames++;
+ lost_sync_count=0;
+ }
+ } /* while */
+
+ /* if we can got full file, we can calculate the accurate duration */
+ /*MODIFICATION : add defence codes for real buffer_size is different with pull_size*/
+ //if (pull_size == file_size) {
+ if (buffer_size == file_size) {
+ gfloat duration_for_one_frame = 0;
+ GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
+
+ GST_INFO_OBJECT (aacparse, "we got total file (%d bytes). do not estimate but make Accurate total duration.", pull_size);
+
+ duration_for_one_frame = (gfloat)AAC_SAMPLE_PER_FRAME / (gfloat)sample_rate;
+ calculated_duration = num_frames * duration_for_one_frame * 1000 * 1000 * 1000;
+
+ GST_INFO_OBJECT (aacparse, "duration_for_one_frame %f ms", duration_for_one_frame);
+ GST_INFO_OBJECT (aacparse, "calculated duration = %"GST_TIME_FORMAT,
+ GST_TIME_ARGS(calculated_duration));
+ /* 0 means disable estimate */
+ gst_base_parse_set_duration (parse, GST_FORMAT_TIME, calculated_duration, 0);
+
+ } else {
+ GST_INFO_OBJECT (aacparse, "we got %d bytes in total file (%"G_GINT64_FORMAT
+ "). can not make accurate duration but Estimate.", pull_size, file_size);
+ frame_duration_us = (1024 * 1000000ll + (sample_rate - 1)) / sample_rate;
+ duration = num_frames * frame_duration_us;
+
+ estimated_bitrate = (gint)((gfloat)(offset * 8) / (gfloat)(duration / 1000));
+ estimated_duration = (GstClockTime)((file_size * 8) / (estimated_bitrate * 1000)) * GST_SECOND;
+
+ GST_INFO_OBJECT (aacparse, "number of frame = %"G_GINT64_FORMAT, num_frames);
+ GST_INFO_OBJECT (aacparse, "duration = %"G_GINT64_FORMAT, duration / 1000000);
+ GST_INFO_OBJECT (aacparse, "byte = %"G_GINT64_FORMAT, offset);
+ GST_INFO_OBJECT (aacparse, "estimated bitrate = %d bps", estimated_bitrate);
+ GST_INFO_OBJECT (aacparse, "estimated duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(estimated_duration));
+
+ gst_base_parse_set_average_bitrate (parse, estimated_bitrate * 1000);
+ /* set update_interval as duration(sec)/2 */
+ gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration, (gint)(duration/2));
+ }
+
+ break;
+ }
+ }
+
+ gst_buffer_unmap(buffer, &map);
+ gst_buffer_unref (buffer);
+ return TRUE;
+}
+
+
+/* perform seek in push based mode:
+ find BYTE position to move to based on time and delegate to upstream
+*/
+static gboolean
+gst_aac_audio_parse_do_push_seek (GstBaseParse * parse,
+ GstPad * pad, GstEvent * event)
+{
+ GstAacParse *aacparse;
+ aacparse = GST_AAC_PARSE(parse);
+
+ gdouble rate;
+ GstFormat format;
+ GstSeekFlags flags;
+ GstSeekType cur_type, stop_type;
+ gint64 cur, stop;
+ gboolean res;
+ gint64 byte_cur;
+ gint64 esimate_byte;
+ gint32 frame_dur;
+ gint64 upstream_total_bytes = 0;
+ GstFormat fmt = GST_FORMAT_BYTES;
+
+ GST_INFO_OBJECT (parse, "doing aac push-based seek");
+
+ gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop);
+
+ /* FIXME, always play to the end */
+ stop = -1;
+
+ /* only forward streaming and seeking is possible */
+ if (rate <= 0)
+ goto unsupported_seek;
+
+ if ( cur == 0 ) {
+ /* handle rewind only */
+ cur_type = GST_SEEK_TYPE_SET;
+ byte_cur = 0;
+ stop_type = GST_SEEK_TYPE_NONE;
+ stop = -1;
+ flags |= GST_SEEK_FLAG_FLUSH;
+ } else {
+ /* handle normal seek */
+ cur_type = GST_SEEK_TYPE_SET;
+ stop_type = GST_SEEK_TYPE_NONE;
+ stop = -1;
+ flags |= GST_SEEK_FLAG_FLUSH;
+
+ esimate_byte = (cur / (1000 * 1000)) * aacparse->frame_byte;
+ if (aacparse->sample_rate> 0)
+ frame_dur = (aacparse->spf * 1000) / aacparse->sample_rate;
+ else
+ goto unsupported_seek;
+ if (frame_dur > 0)
+ byte_cur = esimate_byte / (frame_dur);
+ else
+ goto unsupported_seek;
+
+ GST_INFO_OBJECT(parse, "frame_byte(%d) spf(%d) rate (%d) ", aacparse->frame_byte, aacparse->spf, aacparse->sample_rate);
+ GST_INFO_OBJECT(parse, "seek cur (%"G_GINT64_FORMAT") = (%"GST_TIME_FORMAT") ", cur, GST_TIME_ARGS (cur));
+ GST_INFO_OBJECT(parse, "esimate_byte(%"G_GINT64_FORMAT") esimate_byte (%d)", esimate_byte, frame_dur );
+ }
+
+ /* obtain real upstream total bytes */
+ if (!gst_pad_peer_query_duration (parse->sinkpad, fmt, &upstream_total_bytes))
+ upstream_total_bytes = 0;
+ GST_INFO_OBJECT (aacparse, "gst_pad_query_peer_duration -upstream_total_bytes (%"G_GUINT64_FORMAT")", upstream_total_bytes);
+ aacparse->file_size = upstream_total_bytes;
+
+ if ( (byte_cur == -1) || (byte_cur > aacparse->file_size))
+ {
+ GST_INFO_OBJECT(parse, "[WEB-ERROR] seek cur (%"G_GINT64_FORMAT") > file_size (%"G_GINT64_FORMAT") ", cur, aacparse->file_size );
+ goto abort_seek;
+ }
+
+ GST_INFO_OBJECT (parse, "Pushing BYTE seek rate %g, " "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur, stop);
+
+ if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
+ GST_INFO_OBJECT (parse, "Requested seek time: %" GST_TIME_FORMAT ", calculated seek offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (cur), byte_cur);
+ }
+
+ /* BYTE seek event */
+ event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur, stop_type, stop);
+ res = gst_pad_push_event (parse->sinkpad, event);
+
+ return res;
+
+ /* ERRORS */
+
+abort_seek:
+ {
+ GST_DEBUG_OBJECT (parse, "could not determine byte position to seek to, " "seek aborted.");
+ return FALSE;
+ }
+
+unsupported_seek:
+ {
+ GST_DEBUG_OBJECT (parse, "unsupported seek, seek aborted.");
+ return FALSE;
+ }
+}
+
+
+static guint
+gst_aac_parse_adts_get_fast_frame_len (const guint8 * data)
+{
+ int length;
+ if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
+ length = ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
+ } else {
+ length = 0;
+ }
+ return length;
+}
+
+static gboolean
+gst_aac_parse_src_eventfunc(GstBaseParse * parse, GstEvent * event)
+{
+ gboolean handled = FALSE;
+ GstAacParse *aacparse;
+ aacparse = GST_AAC_PARSE(parse);
+
+ GST_DEBUG("Entering gst_aac_parse_src_eventfunc header type = %d", aacparse->header_type);
+ if(aacparse->header_type == DSPAAC_HEADER_ADTS)
+ return gst_aac_parse_adts_src_eventfunc (parse, event);
+ else
+ goto aac_seek_null_exit;
+aac_seek_null_exit:
+
+ /* call baseparse src_event function to handle event */
+ handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
+ return handled;
+}
+
+/**
+ * gst_aac_parse_adts_src_eventfunc:
+ * @parse: #GstBaseParse. #event
+ *
+ * before baseparse handles seek event, make full amr index table.
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+{
+ gboolean handled = FALSE;
+ GstAacParse *aacparse;
+ aacparse = GST_AAC_PARSE (parse);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:
+ {
+ GstFlowReturn res = GST_FLOW_OK;
+ gint64 base_offset = 0, sync_offset = 0, cur = 0;
+ gint32 frame_count = 1; /* do not add first frame because it is already in index table */
+ gint64 second_count = 0; /* initial 1 second */
+ gint64 total_file_size = 0, start_offset = 0;
+ GstClockTime current_ts = GST_CLOCK_TIME_NONE;
+ GstPadMode pad_mode = GST_PAD_MODE_NONE;
+ gboolean large_file_flag = FALSE;
+
+ /* check baseparse define these fuction */
+ gst_base_parse_get_pad_mode(parse, &pad_mode);
+ if (pad_mode != GST_PAD_MODE_PULL) {
+ gboolean ret = FALSE;
+ GST_INFO_OBJECT (aacparse, "aac parser is PUSH MODE.");
+ GstPad* srcpad = parse->srcpad;
+ /* check NULL */
+ ret = gst_aac_audio_parse_do_push_seek(parse, srcpad, event);
+ gst_object_unref(srcpad);
+ return ret;
+ }
+ gst_base_parse_get_upstream_size(parse, &total_file_size);
+ gst_base_parse_get_index_last_offset(parse, &start_offset);
+ gst_base_parse_get_index_last_ts(parse, ¤t_ts);
+
+ if (total_file_size > AAC_LARGE_FILE_SIZE ) {
+ large_file_flag = TRUE;
+ gst_base_parse_set_seek_mode(parse, 0);
+ GST_INFO_OBJECT (aacparse, "larger than big size (2MB).");
+ goto aac_seek_null_exit;
+ }
+
+ GST_DEBUG("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK enter");
+
+ if (total_file_size == 0 || start_offset >= total_file_size) {
+ GST_ERROR("last index offset %d is larger than file size %d", start_offset, total_file_size);
+ break;
+ }
+
+ gst_event_parse_seek (event, NULL, NULL, NULL, NULL, &cur, NULL, NULL);
+ if (cur <= current_ts) {
+ GST_INFO("seek to %"GST_TIME_FORMAT" within index table %"GST_TIME_FORMAT". do not make index table",
+ GST_TIME_ARGS(cur), GST_TIME_ARGS(current_ts));
+ break;
+ } else {
+ GST_INFO("seek to %"GST_TIME_FORMAT" without index table %"GST_TIME_FORMAT". make index table",
+ GST_TIME_ARGS(cur), GST_TIME_ARGS(current_ts));
+ }
+
+ GST_INFO("make AAC(ADTS) Index Table. file_size = %"G_GINT64_FORMAT" last idx offset=%"G_GINT64_FORMAT
+ ", last idx ts=%"GST_TIME_FORMAT, total_file_size, start_offset, GST_TIME_ARGS(current_ts));
+
+ base_offset = start_offset; /* set base by start offset */
+ second_count = current_ts + GST_SECOND; /* 1sec */
+
+ /************************************/
+ /* STEP 0: Setting parse information */
+ /************************************/
+ aacparse->spf = aacparse->frame_samples;
+ aacparse->frame_duration = (aacparse->spf * 1000 * 100) / aacparse->sample_rate; /* duration per frame (msec) */
+ aacparse->frame_per_sec = (aacparse->sample_rate) / aacparse->spf; /* frames per second (ea) */
+
+ /************************************/
+ /* STEP 1: MAX_PULL_RANGE_BUF cycle */
+ /************************************/
+ while (total_file_size - base_offset >= AAC_MAX_PULL_RANGE_BUF) {
+ gint64 offset = 0;
+ GstBuffer *buffer = NULL;
+ guint8 *buf = NULL;
+
+ GST_INFO("gst_pad_pull_range %d bytes (from %"G_GINT64_FORMAT") use max size", AAC_MAX_PULL_RANGE_BUF, base_offset);
+ res = gst_pad_pull_range (parse->sinkpad, base_offset, base_offset + AAC_MAX_PULL_RANGE_BUF, &buffer);
+ if (res != GST_FLOW_OK) {
+ GST_ERROR ("gst_pad_pull_range failed!");
+ break;
+ }
+
+ GstMapInfo map;
+ gst_buffer_map(buffer, &map, GST_MAP_READ);
+ buf = map.data;
+ if (buf == NULL) {
+ gst_buffer_unmap(buffer, &map);
+ GST_WARNING("buffer is NULL in make aac seek table's STEP1");
+ gst_buffer_unref (buffer);
+ goto aac_seek_null_exit;
+ }
+
+ while (offset <= AAC_MAX_PULL_RANGE_BUF) {
+ gint frame_size = 0;
+ guint32 header;
+
+ /* make sure the values in the frame header look sane */
+ frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
+
+ if ((frame_size > 0) && (frame_size < (AAC_MAX_PULL_RANGE_BUF - offset))) {
+ if (current_ts > second_count) { /* 1 sec == xx frames. we make idx per sec */
+ gst_base_parse_add_index_entry (parse, base_offset +offset, current_ts, TRUE, TRUE); /* force */
+ GST_DEBUG("Adding index ts=%"GST_TIME_FORMAT" offset %"G_GINT64_FORMAT,
+ GST_TIME_ARGS(current_ts), base_offset + offset);
+ second_count += GST_SECOND; /* 1sec */
+ }
+
+ current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
+ offset += frame_size;
+ buf += frame_size;
+ frame_count++;
+ } else if (frame_size >= (AAC_MAX_PULL_RANGE_BUF - offset)) {
+ GST_DEBUG("we need refill buffer");
+ break;
+ } else {
+ GST_WARNING("we lost sync");
+ buf++;
+ offset++;
+ }
+ } /* while */
+
+ base_offset = base_offset + offset;
+
+ gst_buffer_unmap(buffer, &map);
+ gst_buffer_unref (buffer);
+ } /* end MAX buffer cycle */
+
+ /*******************************/
+ /* STEP 2: Remain Buffer cycle */
+ /*******************************/
+ if (total_file_size - base_offset > 0) {
+ gint64 offset = 0;
+ GstBuffer *buffer = NULL;
+ guint8 *buf = NULL;
+
+ GST_INFO("gst_pad_pull_range %"G_GINT64_FORMAT" bytes (from %"G_GINT64_FORMAT") use remain_buf size",
+ total_file_size - base_offset, base_offset);
+ res = gst_pad_pull_range (parse->sinkpad, base_offset, total_file_size, &buffer);
+ if (res != GST_FLOW_OK) {
+ GST_ERROR ("gst_pad_pull_range failed!");
+ break;
+ }
+
+ GstMapInfo map;
+ gst_buffer_map(buffer, &map, GST_MAP_READ);
+ buf = map.data;
+ if (buf == NULL) {
+ gst_buffer_unmap(buffer, &map);
+ GST_WARNING("buffer is NULL in make aac seek table's STEP2");
+ gst_buffer_unref (buffer);
+ goto aac_seek_null_exit;
+ }
+
+ while (base_offset + offset < total_file_size) {
+ gint frame_size = 0;
+ guint32 header;
+
+ /* make sure the values in the frame header look sane */
+ frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
+
+ if ((frame_size > 0) && (frame_size <= (total_file_size - (base_offset + offset)))) {
+ if (current_ts > second_count) { /* 1 sec == xx frames. we make idx per sec */
+ gst_base_parse_add_index_entry (parse, base_offset +offset, current_ts, TRUE, TRUE); /* force */
+ GST_DEBUG("Adding index ts=%"GST_TIME_FORMAT" offset %"G_GINT64_FORMAT,
+ GST_TIME_ARGS(current_ts), base_offset + offset);
+ second_count += GST_SECOND; /* 1sec */
+ }
+
+ current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
+ offset += frame_size;
+ buf += frame_size;
+ frame_count++;
+ } else if (frame_size == 0) {
+ GST_DEBUG("Frame size is 0 so, Decoding end..");
+ break;
+ } else {
+ GST_WARNING("we lost sync");
+ buf++;
+ offset++;
+ }
+ } /* while */
+
+ gst_buffer_unmap(buffer, &map);
+ gst_buffer_unref (buffer);
+ } /* end remain_buf buffer cycle */
+
+ GST_DEBUG("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK leave");
+ }
+ break;
+
+ default:
+ break;
+ }
+
+aac_seek_null_exit:
+
+ /* call baseparse src_event function to handle event */
+ handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
+ return handled;
+}
+#endif //end of #ifdef GST_EXT_AACPARSE_MODIFICATION
\ No newline at end of file