diff options
| author | Tim-Philipp Müller <tim@centricular.net> | 2006-08-22 12:28:24 +0000 | 
|---|---|---|
| committer | Tim-Philipp Müller <tim@centricular.net> | 2006-08-22 12:28:24 +0000 | 
| commit | ad67773c8dbb68281b5dba2ce370e1b97b6dfbba (patch) | |
| tree | bc60c20e2ecb980948d1905d673f1981b080f3c3 | |
| parent | 76ff577a41980357d999369bdce816df4c0f9152 (diff) | |
ext/flac/gstflacdec.*: Make flac-in-ogg work (#352100).
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_scan_got_frame),
(gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_sink_event), (gst_flac_dec_chain),
(gst_flac_dec_src_query):
* ext/flac/gstflacdec.h:
Make flac-in-ogg work (#352100).
| -rw-r--r-- | ChangeLog | 9 | ||||
| -rw-r--r-- | ext/flac/gstflacdec.c | 69 | ||||
| -rw-r--r-- | ext/flac/gstflacdec.h | 2 | 
3 files changed, 71 insertions, 9 deletions
@@ -1,5 +1,14 @@  2006-08-22  Tim-Philipp Müller  <tim at centricular dot net> +	* ext/flac/gstflacdec.c: (gst_flac_dec_scan_got_frame), +	(gst_flac_dec_write), (gst_flac_dec_loop), +	(gst_flac_dec_sink_event), (gst_flac_dec_chain), +	(gst_flac_dec_src_query): +	* ext/flac/gstflacdec.h: +	  Make flac-in-ogg work (#352100). + +2006-08-22  Tim-Philipp Müller  <tim at centricular dot net> +  	* gst/monoscope/gstmonoscope.c: (gst_monoscope_chain):  	  Don't unref buffers of which we've already given away  	  ownership to the adapter. diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c index 51ac28a9..c3affa16 100644 --- a/ext/flac/gstflacdec.c +++ b/ext/flac/gstflacdec.c @@ -444,9 +444,11 @@ gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, guint8 * data, guint size,      *last_sample_num = val;     /* FIXME: + length of last block in samples */    } -  GST_DEBUG_OBJECT (flacdec, "last sample %" G_GINT64_FORMAT " = %" -      GST_TIME_FORMAT, *last_sample_num, -      GST_TIME_ARGS (*last_sample_num * GST_SECOND / flacdec->sample_rate)); +  if (flacdec->sample_rate > 0) { +    GST_DEBUG_OBJECT (flacdec, "last sample %" G_GINT64_FORMAT " = %" +        GST_TIME_FORMAT, *last_sample_num, +        GST_TIME_ARGS (*last_sample_num * GST_SECOND / flacdec->sample_rate)); +  }    return TRUE;  } @@ -805,6 +807,13 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,      goto done;    } +  if (flacdec->cur_granulepos != GST_BUFFER_OFFSET_NONE) { +    /* this should be fine since it should be one flac frame per ogg packet */ +    flacdec->segment.last_stop = flacdec->cur_granulepos - samples; +    GST_LOG_OBJECT (flacdec, "granulepos = %" G_GINT64_FORMAT ", samples = %u", +        flacdec->cur_granulepos, samples); +  } +    GST_BUFFER_TIMESTAMP (outbuf) =        gst_util_uint64_scale_int (flacdec->segment.last_stop, GST_SECOND,        frame->header.sample_rate); @@ -843,7 +852,7 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,    if (!flacdec->seeking) {      GST_DEBUG ("pushing %d samples at offset %" G_GINT64_FORMAT -        "(%" GST_TIME_FORMAT " + %" GST_TIME_FORMAT ")", +        " (%" GST_TIME_FORMAT " + %" GST_TIME_FORMAT ")",          samples, GST_BUFFER_OFFSET (outbuf),          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),          GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf))); @@ -908,6 +917,8 @@ gst_flac_dec_loop (GstPad * sinkpad)      flacdec->init = FALSE;    } +  flacdec->cur_granulepos = GST_BUFFER_OFFSET_NONE; +    flacdec->last_flow = GST_FLOW_OK;    GST_LOG_OBJECT (flacdec, "processing single"); @@ -1032,13 +1043,32 @@ gst_flac_dec_sink_event (GstPad * pad, GstEvent * event)      }      case GST_EVENT_NEWSEGMENT:{        GstFormat fmt; +      gboolean update; +      gdouble rate, applied_rate; +      gint64 cur, stop, time; + +      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, +          &fmt, &cur, &stop, &time); -      gst_event_parse_new_segment (event, NULL, NULL, &fmt, NULL, NULL, NULL);        if (fmt == GST_FORMAT_TIME) { +        GstFormat dformat = GST_FORMAT_DEFAULT; +          GST_DEBUG_OBJECT (dec, "newsegment event in TIME format => framed");          dec->framed = TRUE;          res = gst_pad_push_event (dec->srcpad, event);          dec->need_newsegment = FALSE; + +        /* this won't work for the first newsegment event though ... */ +        if (gst_flac_dec_convert_src (dec->srcpad, GST_FORMAT_TIME, cur, +                &dformat, &cur) && cur != -1 && +            gst_flac_dec_convert_src (dec->srcpad, GST_FORMAT_TIME, stop, +                &dformat, &stop) && stop != -1) { +          gst_segment_set_newsegment_full (&dec->segment, update, rate, +              applied_rate, dformat, cur, stop, time); +          GST_DEBUG_OBJECT (dec, "segment %" GST_SEGMENT_FORMAT, &dec->segment); +        } else { +          GST_WARNING_OBJECT (dec, "couldn't convert time => samples"); +        }        } else if (fmt == GST_FORMAT_BYTES || TRUE) {          GST_DEBUG_OBJECT (dec, "newsegment event in %s format => not framed",              gst_format_get_name (fmt)); @@ -1075,6 +1105,7 @@ gst_flac_dec_chain (GstPad * pad, GstBuffer * buf)  {    FLAC__SeekableStreamDecoderState s;    GstFlacDec *dec; +  gboolean got_audio_frame;    dec = GST_FLAC_DEC (GST_PAD_PARENT (pad)); @@ -1099,6 +1130,22 @@ gst_flac_dec_chain (GstPad * pad, GstBuffer * buf)      FLAC__stream_decoder_flush (dec->stream_decoder);    } +  if (dec->framed) { +    gint64 unused; + +    /* check if this is a flac audio frame (rather than a header or junk) */ +    got_audio_frame = gst_flac_dec_scan_got_frame (dec, GST_BUFFER_DATA (buf), +        GST_BUFFER_SIZE (buf), &unused); + +    /* oggdemux will set granulepos in OFFSET_END instead of timestamp */ +    if (got_audio_frame && !GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { +      dec->cur_granulepos = GST_BUFFER_OFFSET_END (buf); +    } +  } else { +    dec->cur_granulepos = GST_BUFFER_OFFSET_NONE; +    got_audio_frame = TRUE; +  } +    gst_adapter_push (dec->adapter, buf);    buf = NULL; @@ -1109,8 +1156,10 @@ gst_flac_dec_chain (GstPad * pad, GstBuffer * buf)       * interface is a bit dumb it seems (if we don't have as much data as       * it wants it will call our read callback repeatedly and the only       * way to stop that is to error out or EOS, which will affect the -     * decoder state). Requiring MAX_BLOCK_SIZE should make sure it -     * always gets enough data to decode at least one block */ +     * decoder state). And the decoder seems to always ask for MAX_BLOCK_SIZE +     * bytes rather than the max. block size from the header). Requiring +     * MAX_BLOCK_SIZE bytes here should make sure it always gets enough data +     * to decode at least one block */      while (gst_adapter_available (dec->adapter) >= FLAC__MAX_BLOCK_SIZE &&          dec->last_flow == GST_FLOW_OK) {        GST_LOG_OBJECT (dec, "%u bytes available", @@ -1120,13 +1169,15 @@ gst_flac_dec_chain (GstPad * pad, GstBuffer * buf)          break;        }      } -  } else { +  } else if (dec->framed && got_audio_frame) {      /* framed - there should always be enough data to decode something */      GST_LOG_OBJECT (dec, "%u bytes available",          gst_adapter_available (dec->adapter));      if (!FLAC__stream_decoder_process_single (dec->stream_decoder)) {        GST_DEBUG_OBJECT (dec, "process_single failed");      } +  } else { +    GST_DEBUG_OBJECT (dec, "don't have all headers yet");    }    return dec->last_flow; @@ -1367,7 +1418,7 @@ gst_flac_dec_src_query (GstPad * pad, GstQuery * query)        if (fmt == GST_FORMAT_TIME && peer && gst_pad_query (peer, query)) {          gst_query_parse_duration (query, NULL, &len);          GST_DEBUG_OBJECT (flacdec, "peer returned duration %" GST_TIME_FORMAT, -            len); +            GST_TIME_ARGS (len));          res = TRUE;          goto done;        } diff --git a/ext/flac/gstflacdec.h b/ext/flac/gstflacdec.h index d2762d5a..c1057ac8 100644 --- a/ext/flac/gstflacdec.h +++ b/ext/flac/gstflacdec.h @@ -73,6 +73,8 @@ struct _GstFlacDec {    /* from the stream info, needed for scanning */    guint16        min_blocksize;    guint16        max_blocksize; + +  gint64         cur_granulepos; /* only used in framed mode (flac-in-ogg) */  };  struct _GstFlacDecClass {  | 
