diff options
| author | Tim-Philipp Müller <tim@centricular.net> | 2005-10-28 15:32:48 +0000 | 
|---|---|---|
| committer | Tim-Philipp Müller <tim@centricular.net> | 2005-10-28 15:32:48 +0000 | 
| commit | 0166570e093c14e10a5c0e64ada784357dc8aa0f (patch) | |
| tree | b7e7b1414331ed2e6a9f349530eb3e273a713553 | |
| parent | a6562db28617c495842d557bc6bc6e3327f7e55a (diff) | |
gst/matroska/: Add SimpleBlock support to matroska demuxer and muxer (part of
Original commit message from CVS:
Reviewed by: Tim-Philipp Müller  <tim at centricular dot net>
* gst/matroska/matroska-demux.c: (gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster):
* gst/matroska/matroska-ids.h:
* gst/matroska/matroska-mux.c: (gst_matroska_mux_class_init),
(gst_matroska_mux_init), (gst_matroska_mux_start),
(gst_matroska_mux_create_buffer_header),
(gst_matroska_mux_write_data), (gst_matroska_mux_set_property),
(gst_matroska_mux_get_property):
* gst/matroska/matroska-mux.h:
Add SimpleBlock support to matroska demuxer and muxer (part of
Matroska v2). (#319731)
| -rw-r--r-- | ChangeLog | 18 | ||||
| -rw-r--r-- | gst/matroska/matroska-demux.c | 53 | ||||
| -rw-r--r-- | gst/matroska/matroska-ids.h | 1 | ||||
| -rw-r--r-- | gst/matroska/matroska-mux.c | 103 | ||||
| -rw-r--r-- | gst/matroska/matroska-mux.h | 3 | 
5 files changed, 147 insertions, 31 deletions
@@ -1,3 +1,21 @@ +2005-10-28  Michal Benes  <michal dot benes at xeris dot cz> + +	Reviewed by: Tim-Philipp Müller  <tim at centricular dot net> + +	* gst/matroska/matroska-demux.c: (gst_matroska_demux_init_stream), +	(gst_matroska_demux_parse_info), +	(gst_matroska_demux_parse_blockgroup_or_simpleblock), +	(gst_matroska_demux_parse_cluster): +	* gst/matroska/matroska-ids.h: +	* gst/matroska/matroska-mux.c: (gst_matroska_mux_class_init), +	(gst_matroska_mux_init), (gst_matroska_mux_start), +	(gst_matroska_mux_create_buffer_header), +	(gst_matroska_mux_write_data), (gst_matroska_mux_set_property), +	(gst_matroska_mux_get_property): +	* gst/matroska/matroska-mux.h: +	  Add SimpleBlock support to matroska demuxer and muxer (part of +	  Matroska v2). (#319731) +  2005-10-28  Wim Taymans  <wim@fluendo.com>  	* ext/jpeg/gstjpegdec.c: (gst_jpeg_dec_init), (gst_jpeg_dec_chain), diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index a605a711..96f53f32 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -1254,9 +1254,9 @@ gst_matroska_demux_init_stream (GstMatroskaDemux * demux)      return FALSE;    }    g_free (doctype); -  if (version > 1) { +  if (version > 2) {      GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), -        ("Demuxer version (1) is too old to read stream version %d", version)); +        ("Demuxer version (2) is too old to read stream version %d", version));      return FALSE;    } @@ -1625,6 +1625,13 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)          break;        } +      case GST_MATROSKA_ID_SEGMENTUID:{ +        /* TODO not yet implemented. */ +        if (!gst_ebml_read_skip (ebml)) +          res = FALSE; +        break; +      } +        default:          GST_WARNING ("Unknown entry 0x%x in info header", id);          /* fall-through */ @@ -2087,8 +2094,8 @@ gst_matroska_demux_add_wvpk_header (GstMatroskaTrackContext * stream,  }  static gboolean -gst_matroska_demux_parse_blockgroup (GstMatroskaDemux * demux, -    guint64 cluster_time) +gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, +    guint64 cluster_time, gboolean is_simpleblock)  {    GstMatroskaTrackContext *stream = NULL;    GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -2101,25 +2108,30 @@ gst_matroska_demux_parse_blockgroup (GstMatroskaDemux * demux,    guint size = 0;    gint *lace_size = NULL;    gint64 time = 0; +  gint flags = 0;    while (!got_error) { -    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) -      goto error; +    if (!is_simpleblock) { +      if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) +        goto error; -    if (demux->level_up) { -      demux->level_up--; -      break; +      if (demux->level_up) { +        demux->level_up--; +        break; +      } +    } else { +      id = GST_MATROSKA_ID_SIMPLEBLOCK;      }      switch (id) {          /* one block inside the group. Note, block parsing is one           * of the harder things, so this code is a bit complicated.           * See http://www.matroska.org/ for documentation. */ +      case GST_MATROSKA_ID_SIMPLEBLOCK:        case GST_MATROSKA_ID_BLOCK:        {          guint64 num;          guint8 *data; -        gint flags = 0;          if (!gst_ebml_read_buffer (ebml, &id, &buf)) {            got_error = TRUE; @@ -2281,6 +2293,9 @@ gst_matroska_demux_parse_blockgroup (GstMatroskaDemux * demux,          break;      } +    if (is_simpleblock) +      break; +      if (demux->level_up) {        demux->level_up--;        break; @@ -2331,6 +2346,13 @@ gst_matroska_demux_parse_blockgroup (GstMatroskaDemux * demux,          stream->pos += GST_BUFFER_DURATION (sub);        } +      if (is_simpleblock) { +        if (flags & 0x80) +          GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT); +        else +          GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT); +      } +        GST_DEBUG ("Pushing data of size %d for stream %d, time=%"            GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT,            GST_BUFFER_SIZE (sub), stream_num, @@ -2394,11 +2416,20 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)          if (!gst_ebml_read_master (ebml, &id)) {            got_error = TRUE;          } else { -          if (!gst_matroska_demux_parse_blockgroup (demux, cluster_time)) +          if (!gst_matroska_demux_parse_blockgroup_or_simpleblock (demux, +                  cluster_time, FALSE))              got_error = TRUE;          }          break; +      case GST_MATROSKA_ID_SIMPLEBLOCK: +      { +        if (!gst_matroska_demux_parse_blockgroup_or_simpleblock (demux, +                cluster_time, TRUE)) +          got_error = TRUE; +        break; +      } +        default:          GST_WARNING ("Unknown entry 0x%x in cluster data", id);          /* fall-through */ diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index a0895a95..ff61efd1 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -117,6 +117,7 @@  /* IDs in the cluster master */  #define GST_MATROSKA_ID_CLUSTERTIMECODE 0xE7  #define GST_MATROSKA_ID_BLOCKGROUP 0xA0 +#define GST_MATROSKA_ID_SIMPLEBLOCK 0xA3  #define GST_MATROSKA_ID_REFERENCEBLOCK 0xFB  /* IDs in the blockgroup master */ diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 4dc81356..ee19fa38 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -42,7 +42,8 @@ enum  enum  {    ARG_0, -  ARG_WRITING_APP +  ARG_WRITING_APP, +  ARG_MATROSKA_VERSION        /* FILL ME */  }; @@ -201,6 +202,10 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)        g_param_spec_string ("writing-app", "Writing application.",            "The name the application that creates the matroska file.",            NULL, G_PARAM_READWRITE)); +  g_object_class_install_property (gobject_class, ARG_MATROSKA_VERSION, +      g_param_spec_int ("version", "Matroska version", +          "This parameter determines what matroska features can be used.", +          1, 2, 1, G_PARAM_READWRITE));    gstelement_class->change_state = gst_matroska_mux_change_state;    gstelement_class->request_new_pad = gst_matroska_mux_request_new_pad; @@ -233,6 +238,7 @@ gst_matroska_mux_init (GstMatroskaMux * mux, GstMatroskaMuxClass * g_class)    /* initialize internal variables */    mux->index = NULL; +  mux->matroska_version = 1;    /* Initialize all variables */    gst_matroska_mux_reset (GST_ELEMENT (mux)); @@ -1000,7 +1006,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)    GTimeVal time = { 0, 0 };    /* we start with a EBML header */ -  gst_ebml_write_header (ebml, "matroska", 1); +  gst_ebml_write_header (ebml, "matroska", mux->matroska_version);    /* start a segment */    mux->segment_pos = @@ -1269,6 +1275,35 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux)    return best;  } + +/** + * gst_matroska_mux_buffer_header: + * @track: Track context. + * @relative_timestamp: relative timestamp of the buffer + * @flags: Buffer flags. + * + * Create a buffer containing buffer header. + *  + * Returns: New buffer. + */ +GstBuffer * +gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track, +    guint16 relative_timestamp, int flags) +{ +  GstBuffer *hdr; + +  hdr = gst_buffer_new_and_alloc (4); +  /* track num - FIXME: what if num >= 0x80 (unlikely)? */ +  GST_BUFFER_DATA (hdr)[0] = track->num | 0x80; +  /* time relative to clustertime */ +  GST_WRITE_UINT16_BE (GST_BUFFER_DATA (hdr) + 1, relative_timestamp); + +  /* flags */ +  GST_BUFFER_DATA (hdr)[3] = flags; + +  return hdr; +} +  /**   * gst_matroska_mux_write_data:   * @mux: #GstMatroskaMux @@ -1284,6 +1319,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)    GstEbmlWrite *ebml = mux->ebml_write;    GstBuffer *buf, *hdr;    guint64 cluster, blockgroup; +  gboolean write_duration; +  guint16 relative_timestamp;    /* which stream to write from? */    best = gst_matroska_mux_best_pad (mux); @@ -1379,32 +1416,52 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)      idx->track = best->track->num;    } -  /* write one blockgroup with one block with -   * one slice (*breath*). -   * FIXME: lacing, etc. */ -  blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP); -  gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK, -      GST_BUFFER_SIZE (buf) + 4); -  hdr = gst_buffer_new_and_alloc (4); -  /* track num - FIXME: what if num >= 0x80 (unlikely)? */ -  GST_BUFFER_DATA (hdr)[0] = best->track->num | 0x80; -  /* time relative to clustertime */ -  *(guint16 *) & GST_BUFFER_DATA (hdr)[1] = GUINT16_TO_BE ( -      (GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time) / mux->time_scale); -  /* flags - no lacing (yet) */ -  GST_BUFFER_DATA (hdr)[3] = 0; -  gst_ebml_write_buffer (ebml, hdr); -  gst_ebml_write_buffer (ebml, buf); +  /* Check if the duration differs from the default duration. */ +  write_duration = FALSE;    if (GST_BUFFER_DURATION_IS_VALID (buf)) {      guint64 block_duration = GST_BUFFER_DURATION (buf);      if (block_duration != best->track->default_duration) { +      write_duration = TRUE; +    } +  } + +  /* write the block, for matroska v2 use SimpleBlock if possible +   * one slice (*breath*). +   * FIXME: lacing, etc. */ +  relative_timestamp = +      (GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time) / mux->time_scale; +  if (mux->matroska_version > 1 && !write_duration) { +    int flags = +        GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80; + +    hdr = +        gst_matroska_mux_create_buffer_header (best->track, relative_timestamp, +        flags); +    gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK, +        GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr)); +    gst_ebml_write_buffer (ebml, hdr); +    gst_ebml_write_buffer (ebml, buf); + +    return gst_ebml_last_write_result (ebml); +  } else { +    blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP); +    hdr = +        gst_matroska_mux_create_buffer_header (best->track, relative_timestamp, +        0); +    gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK, +        GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr)); +    gst_ebml_write_buffer (ebml, hdr); +    gst_ebml_write_buffer (ebml, buf); +    if (write_duration) { +      guint64 block_duration = GST_BUFFER_DURATION (buf); +        gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION,            block_duration / mux->time_scale);      } +    gst_ebml_write_master_finish (ebml, blockgroup); +    return gst_ebml_last_write_result (ebml);    } -  gst_ebml_write_master_finish (ebml, blockgroup); -  return gst_ebml_last_write_result (ebml);  } @@ -1504,6 +1561,9 @@ gst_matroska_mux_set_property (GObject * object,        g_free (mux->writing_app);        mux->writing_app = g_strdup (g_value_get_string (value));        break; +    case ARG_MATROSKA_VERSION: +      mux->matroska_version = g_value_get_int (value); +      break;      default:        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);        break; @@ -1523,6 +1583,9 @@ gst_matroska_mux_get_property (GObject * object,      case ARG_WRITING_APP:        g_value_set_string (value, mux->writing_app);        break; +    case ARG_MATROSKA_VERSION: +      g_value_set_int (value, mux->matroska_version); +      break;      default:        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);        break; diff --git a/gst/matroska/matroska-mux.h b/gst/matroska/matroska-mux.h index 15f113cc..2f1d2db4 100644 --- a/gst/matroska/matroska-mux.h +++ b/gst/matroska/matroska-mux.h @@ -94,6 +94,9 @@ typedef struct _GstMatroskaMux {    /* Application name (for the writing application header element) */    gchar          *writing_app; +  /* Matroska version. */ +  guint          matroska_version; +    /* state */    GstMatroskaMuxState state;  | 
