gst/matroska/ebml-write.c: Use GDOUBLE_TO_BE() instead of (probably slower) custom code.

Original commit message from CVS:
* gst/matroska/ebml-write.c: (gst_ebml_write_float):
Use GDOUBLE_TO_BE() instead of (probably slower) custom code.
* gst/matroska/matroska-demux.c: (gst_matroska_demux_base_init),
(gst_matroska_demux_class_init), (gst_matroska_demux_init),
(gst_matroska_track_free), (gst_matroska_demux_encoding_cmp),
(gst_matroska_demux_read_track_encodings),
(gst_matroska_demux_add_stream),
(gst_matroska_demux_handle_src_query),
(gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_index_cuetrack),
(gst_matroska_demux_parse_index_pointentry),
(gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_metadata_id_simple_tag),
(gst_matroska_demux_parse_metadata),
(gst_matroska_demux_add_wvpk_header), (gst_matroska_decode_buffer),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster),
(gst_matroska_demux_parse_contents_seekentry),
(gst_matroska_demux_loop_stream_parse_id),
(gst_matroska_demux_loop), (gst_matroska_demux_video_caps),
(gst_matroska_demux_audio_caps),
(gst_matroska_demux_subtitle_caps):
* gst/matroska/matroska-demux.h:
* gst/matroska/matroska-ids.c:
(gst_matroska_track_init_subtitle_context):
* gst/matroska/matroska-ids.h:
* gst/matroska/matroska-mux.c: (gst_matroska_mux_base_init),
(gst_matroska_mux_class_init), (gst_matroska_mux_init),
(gst_matroska_mux_create_uid), (gst_matroska_mux_reset),
(gst_matroska_mux_video_pad_setcaps),
(gst_matroska_mux_audio_pad_setcaps),
(gst_matroska_mux_subtitle_pad_setcaps),
(gst_matroska_mux_request_new_pad),
(gst_matroska_mux_track_header), (gst_matroska_mux_start),
(gst_matroska_mux_write_simple_tag), (gst_matroska_mux_finish),
(gst_matroska_mux_write_data), (gst_matroska_mux_collected),
(gst_matroska_mux_set_property):
Add many FIXMEs/TODOs all over the matroska muxer and demuxer
elements, do some checks for valid values in the demuxer, handle
tracktimecodescale in the demuxer, set correct default values for all
settings in the demuxer, review and add all missing matroska
IDs and some more raw YUV formats, and some trivial cleanup.
This commit is contained in:
Sebastian Dröge 2008-06-10 10:44:53 +00:00
parent 74e9eb72c5
commit a778b414b8
7 changed files with 1023 additions and 313 deletions

View file

@ -1,3 +1,49 @@
2008-06-10 Sebastian Dröge <slomo@circular-chaos.org>
* gst/matroska/ebml-write.c: (gst_ebml_write_float):
Use GDOUBLE_TO_BE() instead of (probably slower) custom code.
* gst/matroska/matroska-demux.c: (gst_matroska_demux_base_init),
(gst_matroska_demux_class_init), (gst_matroska_demux_init),
(gst_matroska_track_free), (gst_matroska_demux_encoding_cmp),
(gst_matroska_demux_read_track_encodings),
(gst_matroska_demux_add_stream),
(gst_matroska_demux_handle_src_query),
(gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_index_cuetrack),
(gst_matroska_demux_parse_index_pointentry),
(gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_metadata_id_simple_tag),
(gst_matroska_demux_parse_metadata),
(gst_matroska_demux_add_wvpk_header), (gst_matroska_decode_buffer),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster),
(gst_matroska_demux_parse_contents_seekentry),
(gst_matroska_demux_loop_stream_parse_id),
(gst_matroska_demux_loop), (gst_matroska_demux_video_caps),
(gst_matroska_demux_audio_caps),
(gst_matroska_demux_subtitle_caps):
* gst/matroska/matroska-demux.h:
* gst/matroska/matroska-ids.c:
(gst_matroska_track_init_subtitle_context):
* gst/matroska/matroska-ids.h:
* gst/matroska/matroska-mux.c: (gst_matroska_mux_base_init),
(gst_matroska_mux_class_init), (gst_matroska_mux_init),
(gst_matroska_mux_create_uid), (gst_matroska_mux_reset),
(gst_matroska_mux_video_pad_setcaps),
(gst_matroska_mux_audio_pad_setcaps),
(gst_matroska_mux_subtitle_pad_setcaps),
(gst_matroska_mux_request_new_pad),
(gst_matroska_mux_track_header), (gst_matroska_mux_start),
(gst_matroska_mux_write_simple_tag), (gst_matroska_mux_finish),
(gst_matroska_mux_write_data), (gst_matroska_mux_collected),
(gst_matroska_mux_set_property):
Add many FIXMEs/TODOs all over the matroska muxer and demuxer
elements, do some checks for valid values in the demuxer, handle
tracktimecodescale in the demuxer, set correct default values for all
settings in the demuxer, review and add all missing matroska
IDs and some more raw YUV formats, and some trivial cleanup.
2008-06-10 Sebastian Dröge <slomo@circular-chaos.org>
* ext/pulse/pulsemixer.c: (gst_pulsemixer_base_init),

View file

@ -25,6 +25,7 @@
#endif
#include <string.h>
#include <gst/floatcast/floatcast.h>
#include "ebml-write.h"
#include "ebml-ids.h"
@ -541,21 +542,12 @@ gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
void
gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
{
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
gint n;
#endif
GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
gst_ebml_write_element_id (buf, id);
gst_ebml_write_element_size (buf, 8);
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
for (n = 0; n < 8; n++) {
GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf)] = ((guint8 *) & num)[7 - n];
GST_BUFFER_SIZE (buf) += 1;
}
#else
num = GDOUBLE_TO_BE (num);
gst_ebml_write_element_data (buf, (guint8 *) & num, 8);
#endif
gst_ebml_write_element_push (ebml, buf);
}

File diff suppressed because it is too large Load diff

View file

@ -40,7 +40,9 @@ G_BEGIN_DECLS
#define GST_IS_MATROSKA_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MATROSKA_DEMUX))
#define GST_MATROSKA_DEMUX_MAX_STREAMS 64
/* The spec says that more than 127 stream is discouraged so
* take this as a limit for now */
#define GST_MATROSKA_DEMUX_MAX_STREAMS 127
typedef enum {
GST_MATROSKA_DEMUX_STATE_START,

View file

@ -109,25 +109,3 @@ gst_matroska_track_init_subtitle_context (GstMatroskaTrackContext ** p_context)
subtitle_context->invalid_utf8 = FALSE;
return TRUE;
}
gboolean
gst_matroska_track_init_complex_context (GstMatroskaTrackContext ** p_context)
{
GstMatroskaTrackComplexContext *complex_context;
g_assert (p_context != NULL && *p_context != NULL);
/* already set up? (track info might come before track type) */
if ((*p_context)->type == GST_MATROSKA_TRACK_TYPE_COMPLEX)
return TRUE;
/* it better not have been set up as some other track type ... */
if ((*p_context)->type != 0) {
g_return_val_if_reached (FALSE);
}
complex_context = g_renew (GstMatroskaTrackComplexContext, *p_context, 1);
*p_context = (GstMatroskaTrackContext *) complex_context;
(*p_context)->type = GST_MATROSKA_TRACK_TYPE_COMPLEX;
return TRUE;
}

View file

@ -30,117 +30,289 @@
* Matroska element IDs. max. 32-bit.
*/
/* toplevel segment */
#define GST_MATROSKA_ID_SEGMENT 0x18538067
/* toplevel Segment */
#define GST_MATROSKA_ID_SEGMENT 0x18538067
/* matroska top-level master IDs */
#define GST_MATROSKA_ID_INFO 0x1549A966
#define GST_MATROSKA_ID_TRACKS 0x1654AE6B
#define GST_MATROSKA_ID_CUES 0x1C53BB6B
#define GST_MATROSKA_ID_TAGS 0x1254C367
#define GST_MATROSKA_ID_SEEKHEAD 0x114D9B74
#define GST_MATROSKA_ID_CLUSTER 0x1F43B675
/* matroska top-level master IDs, childs of Segment */
#define GST_MATROSKA_ID_SEGMENTINFO 0x1549A966
#define GST_MATROSKA_ID_TRACKS 0x1654AE6B
#define GST_MATROSKA_ID_CUES 0x1C53BB6B
#define GST_MATROSKA_ID_TAGS 0x1254C367
#define GST_MATROSKA_ID_SEEKHEAD 0x114D9B74
#define GST_MATROSKA_ID_CLUSTER 0x1F43B675
#define GST_MATROSKA_ID_ATTACHMENTS 0x1941A469
#define GST_MATROSKA_ID_CHAPTERS 0x1043A770
/* IDs in the info master */
#define GST_MATROSKA_ID_TIMECODESCALE 0x2AD7B1
#define GST_MATROSKA_ID_DURATION 0x4489
#define GST_MATROSKA_ID_WRITINGAPP 0x5741
#define GST_MATROSKA_ID_MUXINGAPP 0x4D80
#define GST_MATROSKA_ID_DATEUTC 0x4461
#define GST_MATROSKA_ID_SEGMENTUID 0x73A4
/* IDs in the SegmentInfo master */
#define GST_MATROSKA_ID_TIMECODESCALE 0x2AD7B1
#define GST_MATROSKA_ID_DURATION 0x4489
#define GST_MATROSKA_ID_WRITINGAPP 0x5741
#define GST_MATROSKA_ID_MUXINGAPP 0x4D80
#define GST_MATROSKA_ID_DATEUTC 0x4461
#define GST_MATROSKA_ID_SEGMENTUID 0x73A4
#define GST_MATROSKA_ID_SEGMENTFILENAME 0x7384
#define GST_MATROSKA_ID_PREVUID 0x3CB923
#define GST_MATROSKA_ID_PREVFILENAME 0x3C83AB
#define GST_MATROSKA_ID_NEXTUID 0x3EB923
#define GST_MATROSKA_ID_NEXTFILENAME 0x3E83BB
#define GST_MATROSKA_ID_TITLE 0x7BA9
#define GST_MATROSKA_ID_SEGMENTFAMILY 0x4444
#define GST_MATROSKA_ID_CHAPTERTRANSLATE 0x6924
/* ID in the tracks master */
#define GST_MATROSKA_ID_TRACKENTRY 0xAE
/* IDs in the ChapterTranslate master */
#define GST_MATROSKA_ID_CHAPTERTRANSLATEEDITIONUID 0x69FC
#define GST_MATROSKA_ID_CHAPTERTRANSLATECODEC 0x69BF
#define GST_MATROSKA_ID_CHAPTERTRANSLATEID 0x69A5
/* IDs in the trackentry master */
#define GST_MATROSKA_ID_TRACKNUMBER 0xD7
#define GST_MATROSKA_ID_TRACKUID 0x73C5
#define GST_MATROSKA_ID_TRACKTYPE 0x83
#define GST_MATROSKA_ID_TRACKAUDIO 0xE1
#define GST_MATROSKA_ID_TRACKVIDEO 0xE0
#define GST_MATROSKA_ID_CODECID 0x86
#define GST_MATROSKA_ID_CODECPRIVATE 0x63A2
#define GST_MATROSKA_ID_CODECNAME 0x258688
#define GST_MATROSKA_ID_CODECINFOURL 0x3B4040
#define GST_MATROSKA_ID_CODECDOWNLOADURL 0x26B240
#define GST_MATROSKA_ID_TRACKNAME 0x536E
#define GST_MATROSKA_ID_TRACKLANGUAGE 0x22B59C
#define GST_MATROSKA_ID_TRACKFLAGENABLED 0xB9
#define GST_MATROSKA_ID_TRACKFLAGDEFAULT 0x88
#define GST_MATROSKA_ID_TRACKFLAGLACING 0x9C
#define GST_MATROSKA_ID_TRACKMINCACHE 0x6DE7
#define GST_MATROSKA_ID_TRACKMAXCACHE 0x6DF8
#define GST_MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
#define GST_MATROSKA_ID_CONTENTENCODINGS 0x6D80
/* ID in the Tracks master */
#define GST_MATROSKA_ID_TRACKENTRY 0xAE
/* IDs in the trackvideo master */
#define GST_MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
#define GST_MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
#define GST_MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
#define GST_MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
#define GST_MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
#define GST_MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
#define GST_MATROSKA_ID_VIDEOSTEREOMODE 0x53B9
#define GST_MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
#define GST_MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524
/* IDs in the TrackEntry master */
#define GST_MATROSKA_ID_TRACKNUMBER 0xD7
#define GST_MATROSKA_ID_TRACKUID 0x73C5
#define GST_MATROSKA_ID_TRACKTYPE 0x83
#define GST_MATROSKA_ID_TRACKAUDIO 0xE1
#define GST_MATROSKA_ID_TRACKVIDEO 0xE0
#define GST_MATROSKA_ID_CONTENTENCODINGS 0x6D80
#define GST_MATROSKA_ID_CODECID 0x86
#define GST_MATROSKA_ID_CODECPRIVATE 0x63A2
#define GST_MATROSKA_ID_CODECNAME 0x258688
#define GST_MATROSKA_ID_TRACKNAME 0x536E
#define GST_MATROSKA_ID_TRACKLANGUAGE 0x22B59C
#define GST_MATROSKA_ID_TRACKFLAGENABLED 0xB9
#define GST_MATROSKA_ID_TRACKFLAGDEFAULT 0x88
#define GST_MATROSKA_ID_TRACKFLAGFORCED 0x55AA
#define GST_MATROSKA_ID_TRACKFLAGLACING 0x9C
#define GST_MATROSKA_ID_TRACKMINCACHE 0x6DE7
#define GST_MATROSKA_ID_TRACKMAXCACHE 0x6DF8
#define GST_MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
#define GST_MATROSKA_ID_TRACKTIMECODESCALE 0x23314F
#define GST_MATROSKA_ID_MAXBLOCKADDITIONID 0x55EE
#define GST_MATROSKA_ID_TRACKATTACHMENTLINK 0x7446
#define GST_MATROSKA_ID_TRACKOVERLAY 0x6FAB
#define GST_MATROSKA_ID_TRACKTRANSLATE 0x6624
/* semi-draft */
#define GST_MATROSKA_ID_TRACKOFFSET 0x537F
/* semi-draft */
#define GST_MATROSKA_ID_CODECSETTINGS 0x3A9697
/* semi-draft */
#define GST_MATROSKA_ID_CODECINFOURL 0x3B4040
/* semi-draft */
#define GST_MATROSKA_ID_CODECDOWNLOADURL 0x26B240
/* semi-draft */
#define GST_MATROSKA_ID_CODECDECODEALL 0xAA
/* IDs in the trackaudio master */
#define GST_MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
#define GST_MATROSKA_ID_AUDIOBITDEPTH 0x6264
#define GST_MATROSKA_ID_AUDIOCHANNELS 0x9F
/* IDs in the TrackTranslate master */
#define GST_MATROSKA_ID_TRACKTRANSLATEEDITIONUID 0x66FC
#define GST_MATROSKA_ID_TRACKTRANSLATECODEC 0x66BF
#define GST_MATROSKA_ID_TRACKTRANSLATETRACKID 0x66A5
/* ID in the cues master */
#define GST_MATROSKA_ID_POINTENTRY 0xBB
/* IDs in the TrackVideo master */
/* NOTE: This one is here only for backward compatibility.
* Use _TRACKDEFAULDURATION */
#define GST_MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
#define GST_MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
#define GST_MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
#define GST_MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2
#define GST_MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
#define GST_MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
#define GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM 0x54AA
#define GST_MATROSKA_ID_VIDEOPIXELCROPTOP 0x54BB
#define GST_MATROSKA_ID_VIDEOPIXELCROPLEFT 0x54CC
#define GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT 0x54DD
#define GST_MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
/* semi-draft */
#define GST_MATROSKA_ID_VIDEOSTEREOMODE 0x53B8
#define GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE 0x54B3
#define GST_MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524
/* semi-draft */
#define GST_MATROSKA_ID_VIDEOGAMMAVALUE 0x2FB523
/* IDs in the TrackAudio master */
#define GST_MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
#define GST_MATROSKA_ID_AUDIOBITDEPTH 0x6264
#define GST_MATROSKA_ID_AUDIOCHANNELS 0x9F
/* semi-draft */
#define GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS 0x7D7B
#define GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ 0x78B5
/* IDs in the TrackContentEncoding master */
#define GST_MATROSKA_ID_CONTENTENCODING 0x6240
/* IDs in the ContentEncoding master */
#define GST_MATROSKA_ID_CONTENTENCODINGORDER 0x5031
#define GST_MATROSKA_ID_CONTENTENCODINGSCOPE 0x5032
#define GST_MATROSKA_ID_CONTENTENCODINGTYPE 0x5033
#define GST_MATROSKA_ID_CONTENTCOMPRESSION 0x5034
#define GST_MATROSKA_ID_CONTENTENCRYPTION 0x5035
/* IDs in the ContentCompression master */
#define GST_MATROSKA_ID_CONTENTCOMPALGO 0x4254
#define GST_MATROSKA_ID_CONTENTCOMPSETTINGS 0x4255
/* IDs in the ContentEncryption master */
#define GST_MATROSKA_ID_CONTENTENCALGO 0x47E1
#define GST_MATROSKA_ID_CONTENTENCKEYID 0x47E2
#define GST_MATROSKA_ID_CONTENTSIGNATURE 0x47E3
#define GST_MATROSKA_ID_CONTENTSIGKEYID 0x47E4
#define GST_MATROSKA_ID_CONTENTSIGALGO 0x47E5
#define GST_MATROSKA_ID_CONTENTSIGHASHALGO 0x47E6
/* ID in the CUEs master */
#define GST_MATROSKA_ID_POINTENTRY 0xBB
/* IDs in the pointentry master */
#define GST_MATROSKA_ID_CUETIME 0xB3
#define GST_MATROSKA_ID_CUETRACKPOSITION 0xB7
#define GST_MATROSKA_ID_CUETIME 0xB3
#define GST_MATROSKA_ID_CUETRACKPOSITIONS 0xB7
/* IDs in the cuetrackposition master */
#define GST_MATROSKA_ID_CUETRACK 0xF7
#define GST_MATROSKA_ID_CUECLUSTERPOSITION 0xF1
/* IDs in the CueTrackPositions master */
#define GST_MATROSKA_ID_CUETRACK 0xF7
#define GST_MATROSKA_ID_CUECLUSTERPOSITION 0xF1
#define GST_MATROSKA_ID_CUEBLOCKNUMBER 0x5378
/* semi-draft */
#define GST_MATROSKA_ID_CUECODECSTATE 0xEA
/* semi-draft */
#define GST_MATROSKA_ID_CUEREFERENCE 0xDB
/* IDs in the tags master */
#define GST_MATROSKA_ID_TAG 0x7373
/* IDs in the CueReference master */
/* semi-draft */
#define GST_MATROSKA_ID_CUEREFTIME 0x96
/* semi-draft */
#define GST_MATROSKA_ID_CUEREFCLUSTER 0x97
/* semi-draft */
#define GST_MATROSKA_ID_CUEREFNUMBER 0x535F
/* semi-draft */
#define GST_MATROSKA_ID_CUEREFCODECSTATE 0xEB
/* in the tag master */
#define GST_MATROSKA_ID_SIMPLETAG 0x67C8
/* IDs in the Tags master */
#define GST_MATROSKA_ID_TAG 0x7373
/* in the simpletag master */
#define GST_MATROSKA_ID_TAGNAME 0x45A3
#define GST_MATROSKA_ID_TAGSTRING 0x4487
/* in the Tag master */
#define GST_MATROSKA_ID_SIMPLETAG 0x67C8
#define GST_MATROSKA_ID_TARGETS 0x63C0
/* IDs in the seekhead master */
#define GST_MATROSKA_ID_SEEKENTRY 0x4DBB
/* in the SimpleTag master */
#define GST_MATROSKA_ID_TAGNAME 0x45A3
#define GST_MATROSKA_ID_TAGSTRING 0x4487
#define GST_MATROSKA_ID_TAGLANGUAGE 0x447A
#define GST_MATROSKA_ID_TAGDEFAULT 0x4484
#define GST_MATROSKA_ID_TAGBINARY 0x4485
/* IDs in the seekpoint master */
#define GST_MATROSKA_ID_SEEKID 0x53AB
#define GST_MATROSKA_ID_SEEKPOSITION 0x53AC
/* in the Targets master */
#define GST_MATROSKA_ID_TARGETTYPEVALUE 0x68CA
#define GST_MATROSKA_ID_TARGETTYPE 0x63CA
#define GST_MATROSKA_ID_TARGETTRACKUID 0x63C5
#define GST_MATROSKA_ID_TARGETEDITIONUID 0x63C5
#define GST_MATROSKA_ID_TARGETCHAPTERUID 0x63C4
#define GST_MATROSKA_ID_TARGETATTACHMENTUID 0x63C6
/* 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 SeekHead master */
#define GST_MATROSKA_ID_SEEKENTRY 0x4DBB
/* IDs in the blockgroup master */
#define GST_MATROSKA_ID_BLOCK 0xA1
#define GST_MATROSKA_ID_BLOCKDURATION 0x9B
/* IDs in the SeekEntry master */
#define GST_MATROSKA_ID_SEEKID 0x53AB
#define GST_MATROSKA_ID_SEEKPOSITION 0x53AC
/* IDs in the contentencodings master */
#define GST_MATROSKA_ID_CONTENTENCODING 0x6240
/* 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
#define GST_MATROSKA_ID_POSITION 0xA7
#define GST_MATROSKA_ID_PREVSIZE 0xAB
/* semi-draft */
#define GST_MATROSKA_ID_ENCRYPTEDBLOCK 0xAF
#define GST_MATROSKA_ID_SILENTTRACKS 0x5854
/* IDS IN THE CONTENTENCODING MASTER */
#define GST_MATROSKA_ID_CONTENTENCODINGORDER 0X5031
#define GST_MATROSKA_ID_CONTENTENCODINGSCOPE 0X5032
#define GST_MATROSKA_ID_CONTENTENCODINGTYPE 0X5033
#define GST_MATROSKA_ID_CONTENTCOMPRESSION 0X5034
#define GST_MATROSKA_ID_CONTENTENCRYPTION 0X5035
/* IDs in the SilentTracks master */
#define GST_MATROSKA_ID_SILENTTRACKNUMBER 0x58D7
/* IDS IN THE CONTENTCOMPRESSION MASTER */
#define GST_MATROSKA_ID_CONTENTCOMPALGO 0X4254
#define GST_MATROSKA_ID_CONTENTCOMPSETTINGS 0X4255
/* IDs in the BlockGroup master */
#define GST_MATROSKA_ID_BLOCK 0xA1
#define GST_MATROSKA_ID_BLOCKDURATION 0x9B
/* semi-draft */
#define GST_MATROSKA_ID_BLOCKVIRTUAL 0xA2
#define GST_MATROSKA_ID_REFERENCEBLOCK 0xFB
#define GST_MATROSKA_ID_BLOCKADDITIONS 0x75A1
#define GST_MATROSKA_ID_REFERENCEPRIORITY 0xFA
/* semi-draft */
#define GST_MATROSKA_ID_REFERENCEVIRTUAL 0xFD
/* semi-draft */
#define GST_MATROSKA_ID_CODECSTATE 0xA4
#define GST_MATROSKA_ID_SLICES 0x8E
/* IDs in the BlockAdditions master */
#define GST_MATROSKA_ID_BLOCKMORE 0xA6
/* IDs in the BlockMore master */
#define GST_MATROSKA_ID_BLOCKADDID 0xEE
#define GST_MATROSKA_ID_BLOCKADDITIONAL 0xA5
/* IDs in the Slices master */
#define GST_MATROSKA_ID_TIMESLICE 0xE8
/* IDs in the TimeSlice master */
#define GST_MATROSKA_ID_LACENUMBER 0xCC
/* semi-draft */
#define GST_MATROSKA_ID_FRAMENUMBER 0xCD
/* semi-draft */
#define GST_MATROSKA_ID_BLOCKADDITIONID 0xCB
/* semi-draft */
#define GST_MATROSKA_ID_TIMESLICEDELAY 0xCE
#define GST_MATROSKA_ID_TIMESLICEDURATION 0xCF
/* IDs in the Attachments master */
#define GST_MATROSKA_ID_ATTACHEDFILE 0x61A7
/* IDs in the AttachedFile master */
#define GST_MATROSKA_ID_FILEDESCRIPTION 0x467E
#define GST_MATROSKA_ID_FILENAME 0x466E
#define GST_MATROSKA_ID_FILEMIMETYPE 0x4660
#define GST_MATROSKA_ID_FILEDATA 0x465C
#define GST_MATROSKA_ID_FILEUID 0x46AE
/* semi-draft */
#define GST_MATROSKA_ID_FILEREFERRAL 0x4675
/* IDs in the Chapters master */
#define GST_MATROSKA_ID_EDITIONENTRY 0x45B9
/* IDs in the EditionEntry master */
#define GST_MATROSKA_ID_EDITIONUID 0x45BC
#define GST_MATROSKA_ID_EDITIONFLAGHIDDEN 0x45BD
#define GST_MATROSKA_ID_EDITIONFLAGDEFAULT 0x45DB
#define GST_MATROSKA_ID_EDITIONFLAGORDERED 0x45DD
#define GST_MATROSKA_ID_CHAPTERATOM 0xB6
/* IDs in the ChapterAtom master */
#define GST_MATROSKA_ID_CHAPTERUID 0x73C4
#define GST_MATROSKA_ID_CHAPTERTIMESTART 0x91
#define GST_MATROSKA_ID_CHAPTERTIMESTOP 0x92
#define GST_MATROSKA_ID_CHAPTERFLAGHIDDEN 0x98
#define GST_MATROSKA_ID_CHAPTERFLAGENABLED 0x4598
#define GST_MATROSKA_ID_CHAPTERSEGMENTUID 0x6E67
#define GST_MATROSKA_ID_CHAPTERSEGMENTEDITIONUID 0x6EBC
#define GST_MATROSKA_ID_CHAPTERPHYSICALEQUIV 0x63C3
#define GST_MATROSKA_ID_CHAPTERTRACK 0x8F
#define GST_MATROSKA_ID_CHAPTERDISPLAY 0x80
#define GST_MATROSKA_ID_CHAPPROCESS 0x6944
/* IDs in the ChapProcess master */
#define GST_MATROSKA_ID_CHAPPROCESSCODECID 0x6955
#define GST_MATROSKA_ID_CHAPPROCESSPRIVATE 0x450D
#define GST_MATROSKA_ID_CHAPPROCESSCOMMAND 0x6911
/* IDs in the ChapProcessCommand master */
#define GST_MATROSKA_ID_CHAPPROCESSTIME 0x6922
#define GST_MATROSKA_ID_CHAPPROCESSDATA 0x6933
/* IDs in the ChapterDisplay master */
#define GST_MATROSKA_ID_CHAPSTRING 0x85
#define GST_MATROSKA_ID_CHAPLANGUAGE 0x437C
#define GST_MATROSKA_ID_CHAPCOUNTRY 0x437E
/* IDs in the ChapterTrack master */
#define GST_MATROSKA_ID_CHAPTERTRACKNUMBER 0x89
/*
* Matroska Codec IDs. Strings.
@ -155,49 +327,61 @@
#define GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3 "V_MPEG4/MS/V3"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG1 "V_MPEG1"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG2 "V_MPEG2"
/* FIXME: not (yet) in the spec! */
#define GST_MATROSKA_CODEC_ID_VIDEO_MJPEG "V_MJPEG"
#define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1 "V_REAL/RV10"
#define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2 "V_REAL/RV20"
#define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3 "V_REAL/RV30"
#define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4 "V_REAL/RV40"
#define GST_MATROSKA_CODEC_ID_VIDEO_THEORA "V_THEORA"
#define GST_MATROSKA_CODEC_ID_VIDEO_QUICKTIME "V_QUICKTIME"
#define GST_MATROSKA_CODEC_ID_VIDEO_SNOW "V_SNOW"
#define GST_MATROSKA_CODEC_ID_VIDEO_DIRAC "V_DIRAC"
/* TODO: Quicktime */
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1 "A_MPEG/L1"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2 "A_MPEG/L2"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3 "A_MPEG/L3"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE "A_PCM/INT/BIG"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE "A_PCM/INT/LIT"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT "A_PCM/FLOAT/IEEE"
#define GST_MATROSKA_CODEC_ID_AUDIO_AC3 "A_AC3"
#define GST_MATROSKA_CODEC_ID_AUDIO_DTS "A_DTS"
#define GST_MATROSKA_CODEC_ID_AUDIO_VORBIS "A_VORBIS"
#define GST_MATROSKA_CODEC_ID_AUDIO_FLAC "A_FLAC"
#define GST_MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG2 "A_AAC/MPEG2/"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG4 "A_AAC/MPEG4/"
#define GST_MATROSKA_CODEC_ID_AUDIO_TTA "A_TTA1"
#define GST_MATROSKA_CODEC_ID_AUDIO_WAVPACK4 "A_WAVPACK4"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4 "A_REAL/28_8"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8 "A_REAL/28_8"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK "A_REAL/COOK"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR "A_REAL/SIPR"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_RALF "A_REAL/RALF"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_ATRC "A_REAL/ATRC"
/* TODO: AC3-9/10 (?), Musepack, Quicktime */
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1 "A_MPEG/L1"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2 "A_MPEG/L2"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3 "A_MPEG/L3"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE "A_PCM/INT/BIG"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE "A_PCM/INT/LIT"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT "A_PCM/FLOAT/IEEE"
#define GST_MATROSKA_CODEC_ID_AUDIO_AC3 "A_AC3"
#define GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID9 "A_AC3/BSID9"
#define GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID10 "A_AC3/BSID10"
#define GST_MATROSKA_CODEC_ID_AUDIO_DTS "A_DTS"
#define GST_MATROSKA_CODEC_ID_AUDIO_VORBIS "A_VORBIS"
#define GST_MATROSKA_CODEC_ID_AUDIO_FLAC "A_FLAC"
#define GST_MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM"
#define GST_MATROSKA_CODEC_ID_AUDIO_TTA "A_TTA1"
#define GST_MATROSKA_CODEC_ID_AUDIO_WAVPACK4 "A_WAVPACK4"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4 "A_REAL/14_4"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8 "A_REAL/28_8"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK "A_REAL/COOK"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR "A_REAL/SIPR"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_RALF "A_REAL/RALF"
#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_ATRC "A_REAL/ATRC"
#define GST_MATROSKA_CODEC_ID_AUDIO_AAC "A_AAC"
#define GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2 "A_AAC/MPEG2/"
#define GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4 "A_AAC/MPEG4/"
#define GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDMC "A_QUICKTIME/QDMC"
#define GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDM2 "A_QUICKTIME/QDM2"
/* Undefined for now:
#define GST_MATROSKA_CODEC_ID_AUDIO_MPC "A_MPC"
*/
#define GST_MATROSKA_CODEC_ID_SUBTITLE_ASCII "S_TEXT/ASCII"
#define GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8 "S_TEXT/UTF8"
#define GST_MATROSKA_CODEC_ID_SUBTITLE_SSA "S_TEXT/SSA"
#define GST_MATROSKA_CODEC_ID_SUBTITLE_ASS "S_TEXT/ASS"
#define GST_MATROSKA_CODEC_ID_SUBTITLE_USF "S_TEXT/USF"
#define GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB "S_VOBSUB"
#define GST_MATROSKA_CODEC_ID_SUBTITLE_BMP "S_IMAGE/BMP"
/*
* Matrodka tags. Strings.
* Matroska tags. Strings.
*/
/* TODO: check for other tags */
#define GST_MATROSKA_TAG_ID_TITLE "TITLE"
#define GST_MATROSKA_TAG_ID_AUTHOR "AUTHOR"
#define GST_MATROSKA_TAG_ID_ALBUM "ALBUM"
@ -208,6 +392,30 @@
#define GST_MATROSKA_TAG_ID_ISRC "ISRC"
#define GST_MATROSKA_TAG_ID_COPYRIGHT "COPYRIGHT"
/*
* TODO: add this tag & mappings
* "URL" -> GST_TAG_LOCATION
* "BPS" -> GST_TAG_BITRATE
* "BPM" -> GST_TAG_BEATS_PER_MINUTE
* "REPLAYGAIN_GAIN" -> GST_TAG_*_GAIN see http://replaygain.hydrogenaudio.org/rg_data_format.html
* "REPLAYGAIN_PEAK" -> GST_TAG_*_PEAK see http://replaygain.hydrogenaudio.org/peak_data_format.html
* "TERMS_OF_USE" -> GST_TAG_LICENSE
* "DATE_RECORDED" -> GST_TAG_DATE
* "COMPOSER" -> GST_TAG_COMPOSER
* "LEAD_PERFORMER" -> GST_TAG_PERFORMER
* "GENRE" -> GST_TAG_GENRE
*
* "TOTAL_PARTS" -> GST_TAG_TRACK_COUNT depending on target
* "PART_NUMBER" -> GST_TAG_TRACK_NUMBER depending on target
*
* "EMAIL" ->
* "ADDRESS" ->
* "FAX" -> GST_TAG_CONTACT
* "PHONE" ->
*
* TODO: maybe add custom gstreamer tags for other standard matroska tags
*/
/*
* Enumerations for various types (mapping from binary
* value to what it actually means).
@ -219,6 +427,7 @@ typedef enum {
GST_MATROSKA_TRACK_TYPE_COMPLEX = 0x3,
GST_MATROSKA_TRACK_TYPE_LOGO = 0x10,
GST_MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,
GST_MATROSKA_TRACK_TYPE_BUTTONS = 0x12,
GST_MATROSKA_TRACK_TYPE_CONTROL = 0x20,
} GstMatroskaTrackType;
@ -244,6 +453,7 @@ typedef enum {
GST_MATROSKA_TRACK_ENABLED = (1<<0),
GST_MATROSKA_TRACK_DEFAULT = (1<<1),
GST_MATROSKA_TRACK_LACING = (1<<2),
GST_MATROSKA_TRACK_FORCED = (1<<3),
GST_MATROSKA_TRACK_SHIFT = (1<<16)
} GstMatroskaTrackFlags;
@ -251,6 +461,7 @@ typedef enum {
GST_MATROSKA_VIDEOTRACK_INTERLACED = (GST_MATROSKA_TRACK_SHIFT<<0)
} GstMatroskaVideoTrackFlags;
/* TODO: check if all fields are used */
typedef struct _GstMatroskaTrackContext {
GstPad *pad;
GstCaps *caps;
@ -266,6 +477,7 @@ typedef struct _GstMatroskaTrackContext {
GstMatroskaTrackFlags flags;
guint64 default_duration;
guint64 pos;
gdouble timecodescale;
gboolean set_discont; /* TRUE = set DISCONT flag on next buffer */
@ -313,12 +525,6 @@ typedef struct _GstMatroskaTrackAudioContext {
guint samplerate, channels, bitdepth;
} GstMatroskaTrackAudioContext;
typedef struct _GstMatroskaTrackComplexContext {
GstMatroskaTrackContext parent;
/* nothing special goes here, apparently */
} GstMatroskaTrackComplexContext;
typedef struct _GstMatroskaTrackSubtitleContext {
GstMatroskaTrackContext parent;
@ -357,6 +563,5 @@ typedef struct _GstMatroskaTrackEncoding {
gboolean gst_matroska_track_init_video_context (GstMatroskaTrackContext ** p_context);
gboolean gst_matroska_track_init_audio_context (GstMatroskaTrackContext ** p_context);
gboolean gst_matroska_track_init_subtitle_context (GstMatroskaTrackContext ** p_context);
gboolean gst_matroska_track_init_complex_context (GstMatroskaTrackContext ** p_context);
#endif /* __GST_MATROSKA_IDS_H__ */

View file

@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
/* TODO: - check everywhere that we don't write invalid values
* - make sure timestamps are correctly scaled everywhere
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -55,6 +59,10 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
"width = (int) [ 16, 4096 ], " \
"height = (int) [ 16, 4096 ] "
/* FIXME:
* * require codec data, etc as needed
*/
static GstStaticPadTemplate videosink_templ =
GST_STATIC_PAD_TEMPLATE ("video_%d",
GST_PAD_SINK,
@ -92,6 +100,7 @@ static GstStaticPadTemplate videosink_templ =
/* FIXME:
* * audio/x-raw-float: endianness needs defining.
* * require codec data, etc as needed
*/
static GstStaticPadTemplate audiosink_templ =
GST_STATIC_PAD_TEMPLATE ("audio_%d",
@ -184,11 +193,6 @@ static void
gst_matroska_mux_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
static const GstElementDetails gst_matroska_mux_details =
GST_ELEMENT_DETAILS ("Matroska muxer",
"Codec/Muxer",
"Muxes video/audio/subtitle streams into a matroska stream",
"Ronald Bultje <rbultje@ronald.bitfreak.net>");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&videosink_templ));
@ -198,7 +202,10 @@ gst_matroska_mux_base_init (gpointer g_class)
gst_static_pad_template_get (&subtitlesink_templ));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_templ));
gst_element_class_set_details (element_class, &gst_matroska_mux_details);
gst_element_class_set_details_simple (element_class, "Matroska muxer",
"Codec/Muxer",
"Muxes video/audio/subtitle streams into a matroska stream",
"Ronald Bultje <rbultje@ronald.bitfreak.net>");
GST_DEBUG_CATEGORY_INIT (matroskamux_debug, "matroskamux", 0,
"Matroska muxer");
@ -208,12 +215,13 @@ static void
gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_matroska_mux_finalize);
gobject_class->finalize = gst_matroska_mux_finalize;
gobject_class->get_property = gst_matroska_mux_get_property;
gobject_class->set_property = gst_matroska_mux_set_property;
@ -246,11 +254,7 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
static void
gst_matroska_mux_init (GstMatroskaMux * mux, GstMatroskaMuxClass * g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
mux->srcpad =
gst_pad_new_from_template (gst_element_class_get_pad_template
(gstelement_class, "src"), "src");
mux->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
@ -301,8 +305,10 @@ static guint32
gst_matroska_mux_create_uid (void)
{
guint32 uid = 0;
GRand *rand = g_rand_new ();
/* FIXME: array needs locking or moved into instance structure */
while (!uid) {
guint i;
@ -357,6 +363,7 @@ static void
gst_matroska_mux_reset (GstElement * element)
{
GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
GSList *walk;
/* reset EBML write */
@ -368,6 +375,7 @@ gst_matroska_mux_reset (GstElement * element)
/* clean up existing streams */
while ((walk = mux->collect->data) != NULL) {
GstMatroskaPad *collect_pad;
GstPad *thepad;
collect_pad = (GstMatroskaPad *) walk->data;
@ -396,7 +404,7 @@ gst_matroska_mux_reset (GstElement * element)
mux->index = NULL;
/* reset timers */
mux->time_scale = 1000000;
mux->time_scale = GST_MSECOND;
mux->duration = 0;
/* reset uid array */
@ -463,9 +471,13 @@ static gboolean
gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
{
GstMatroskaTrackContext *context;
GstMatroskaPad *collect_pad;
GstMatroskaMux *mux;
GstTagList *list;
gboolean ret;
mux = GST_MATROSKA_MUX (gst_pad_get_parent (pad));
@ -514,12 +526,19 @@ static gboolean
gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
{
GstMatroskaTrackContext *context = NULL;
GstMatroskaTrackVideoContext *videocontext;
GstMatroskaMux *mux;
GstMatroskaPad *collect_pad;
GstStructure *structure;
const gchar *mimetype;
gint width, height, pixel_width, pixel_height;
gint fps_d, fps_n;
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@ -578,6 +597,11 @@ skip_details:
videocontext->eye_mode = GST_MATROSKA_EYE_MODE_MONO;
videocontext->fourcc = 0;
/* TODO: - check if we handle all codecs by the spec, i.e. codec private
* data and other settings
* - add new formats
*/
/* find type */
if (!strcmp (mimetype, "video/x-raw-yuv")) {
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
@ -594,7 +618,9 @@ skip_details:
|| !strcmp (mimetype, "video/x-dv")
|| !strcmp (mimetype, "video/x-h263")) {
BITMAPINFOHEADER *bih;
const GValue *codec_data;
gint size = sizeof (BITMAPINFOHEADER);
bih = g_new0 (BITMAPINFOHEADER, 1);
@ -666,6 +692,7 @@ skip_details:
if (codec_data != NULL) {
guint8 *priv_data = NULL;
guint priv_data_size = 0;
GstBuffer *codec_data_buf = g_value_peek_pointer (codec_data);
@ -735,8 +762,11 @@ xiph3_streamheader_to_codecdata (const GValue * streamheader,
GstMatroskaTrackContext * context, GstBuffer ** p_buf0)
{
GstBuffer *buf[3];
GArray *bufarr;
guint8 *priv_data;
guint i, offset, priv_data_size;
if (streamheader == NULL)
@ -835,6 +865,7 @@ vorbis_streamheader_to_codecdata (const GValue * streamheader,
} else {
if (memcmp (GST_BUFFER_DATA (buf0) + 1, "vorbis", 6) == 0) {
GstMatroskaTrackAudioContext *audiocontext;
guint8 *hdr;
hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 4;
@ -865,7 +896,9 @@ theora_streamheader_to_codecdata (const GValue * streamheader,
GST_WARNING ("First header not a theora identification header, ignoring");
} else {
GstMatroskaTrackVideoContext *videocontext;
guint fps_num, fps_denom, par_num, par_denom;
guint8 *hdr;
hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 3 + 2 + 2;
@ -920,11 +953,17 @@ static gboolean
gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
{
GstMatroskaTrackContext *context = NULL;
GstMatroskaTrackAudioContext *audiocontext;
GstMatroskaMux *mux;
GstMatroskaPad *collect_pad;
const gchar *mimetype;
gint samplerate = 0, channels = 0;
GstStructure *structure;
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@ -949,6 +988,11 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
audiocontext->bitdepth = 0;
context->default_duration = 0;
/* TODO: - check if we handle all codecs by the spec, i.e. codec private
* data and other settings
* - add new formats
*/
if (!strcmp (mimetype, "audio/mpeg")) {
gint mpegversion = 0;
@ -957,6 +1001,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
case 1:{
gint layer;
/* FIXME: number of samples per frame also depends on the mpegversion
* which we don't pass as a caps field
*/
gst_structure_get_int (structure, "layer", &layer);
switch (layer) {
case 1:
@ -980,10 +1028,12 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
break;
}
case 2:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2 "MAIN");
context->codec_id =
g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2 "MAIN");
break;
case 4:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4 "MAIN");
context->codec_id =
g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4 "MAIN");
break;
default:
return FALSE;
@ -992,6 +1042,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
return TRUE;
} else if (!strcmp (mimetype, "audio/x-raw-int")) {
gint endianness, width, depth;
gboolean signedness;
if (!gst_structure_get_int (structure, "width", &width) ||
@ -1078,7 +1129,8 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
static gboolean
gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
{
/* Consider this as boilerplate code for now. There is
/* FIXME:
* Consider this as boilerplate code for now. There is
* no single subtitle creation element in GStreamer,
* neither do I know how subtitling works at all. */
@ -1101,30 +1153,36 @@ gst_matroska_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * pad_name)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
GstMatroskaPad *collect_pad;
GstPad *newpad = NULL;
gchar *name = NULL;
GstPadSetCapsFunction setcapsfunc = NULL;
GstMatroskaTrackContext *context = NULL;
if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
name = g_strdup_printf ("audio_%d", mux->num_a_streams++);
setcapsfunc = gst_matroska_mux_audio_pad_setcaps;
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
context = (GstMatroskaTrackContext *)
g_new0 (GstMatroskaTrackAudioContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
context->name = g_strdup ("Audio");
} else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
name = g_strdup_printf ("video_%d", mux->num_v_streams++);
setcapsfunc = gst_matroska_mux_video_pad_setcaps;
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
context = (GstMatroskaTrackContext *)
g_new0 (GstMatroskaTrackVideoContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
context->name = g_strdup ("Video");
} else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%d")) {
name = g_strdup_printf ("subtitle_%d", mux->num_t_streams++);
setcapsfunc = gst_matroska_mux_subtitle_pad_setcaps;
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
context = (GstMatroskaTrackContext *)
g_new0 (GstMatroskaTrackSubtitleContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
@ -1138,6 +1196,8 @@ gst_matroska_mux_request_new_pad (GstElement * element,
g_free (name);
collect_pad = (GstMatroskaPad *)
gst_collect_pads_add_pad (mux->collect, newpad, sizeof (GstMatroskaPad));
/* TODO: check default values for the context */
context->flags = GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT;
collect_pad->track = context;
collect_pad->buffer = NULL;
@ -1174,12 +1234,14 @@ static void
gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
{
GstMatroskaMux *mux;
GSList *walk;
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
GstCollectData *cdata = (GstCollectData *) walk->data;
GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
if (cdata->pad == pad) {
@ -1219,8 +1281,11 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
GstMatroskaTrackContext * context)
{
GstEbmlWrite *ebml = mux->ebml_write;
guint64 master;
/* TODO: check if everything necessary is written and check default values */
/* track type goes before the type-specific stuff */
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
@ -1298,6 +1363,7 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
/* FIXME: until we have a nice way of getting the codecname
* out of the caps, I'm not going to enable this. Too much
* (useless, double, boring) work... */
/* TODO: Use value from tags if any */
/*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
context->codec_name); */
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
@ -1314,7 +1380,8 @@ static void
gst_matroska_mux_start (GstMatroskaMux * mux)
{
GstEbmlWrite *ebml = mux->ebml_write;
guint32 seekhead_id[] = { GST_MATROSKA_ID_INFO,
guint32 seekhead_id[] = { GST_MATROSKA_ID_SEGMENTINFO,
GST_MATROSKA_ID_TRACKS,
GST_MATROSKA_ID_CUES,
GST_MATROSKA_ID_SEEKHEAD,
@ -1322,11 +1389,17 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
0
};
guint64 master, child;
GSList *collected;
int i;
guint tracknum = 1;
GstClockTime duration = 0;
guint32 *segment_uid = (guint32 *) g_malloc (16);
GRand *rand = g_rand_new ();
GTimeVal time = { 0, 0 };
@ -1354,7 +1427,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
/* segment info */
mux->info_pos = ebml->pos;
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_INFO);
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
for (i = 0; i < 4; i++) {
segment_uid[i] = g_rand_int (rand);
}
@ -1368,8 +1441,11 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
for (collected = mux->collect->data; collected;
collected = g_slist_next (collected)) {
GstMatroskaPad *collect_pad;
GstFormat format = GST_FORMAT_TIME;
GstPad *thepad;
gint64 trackduration;
collect_pad = (GstMatroskaPad *) collected->data;
@ -1406,6 +1482,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
collected = g_slist_next (collected)) {
GstMatroskaPad *collect_pad;
GstPad *thepad;
collect_pad = (GstMatroskaPad *) collected->data;
@ -1429,6 +1506,7 @@ static void
gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
gpointer data)
{
/* TODO: more sensible tag mappings */
struct
{
gchar *matroska_tagname;
@ -1446,11 +1524,14 @@ gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}
};
GstEbmlWrite *ebml = (GstEbmlWrite *) data;
guint i;
guint64 simpletag_master;
for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
if (strcmp (tagname_gst, tag) == 0) {
@ -1486,9 +1567,13 @@ static void
gst_matroska_mux_finish (GstMatroskaMux * mux)
{
GstEbmlWrite *ebml = mux->ebml_write;
guint64 pos;
guint64 duration = 0;
GSList *collected;
GstTagList *tags;
/* finish last cluster */
@ -1499,6 +1584,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
/* cues */
if (mux->index != NULL) {
guint n;
guint64 master, pointentry_master, trackpos_master;
mux->cues_pos = ebml->pos;
@ -1513,7 +1599,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
idx->time / mux->time_scale);
trackpos_master = gst_ebml_write_master_start (ebml,
GST_MATROSKA_ID_CUETRACKPOSITION);
GST_MATROSKA_ID_CUETRACKPOSITIONS);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
idx->pos - mux->segment_master);
@ -1527,6 +1613,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
if (mux->meta_index != NULL) {
guint n;
guint64 master, seekentry_master;
mux->meta_pos = ebml->pos;
@ -1554,6 +1641,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
if (tags != NULL) {
guint64 master_tags, master_tag;
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
mux->tags_pos = ebml->pos;
master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
@ -1618,6 +1706,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
for (collected = mux->collect->data; collected;
collected = g_slist_next (collected)) {
GstMatroskaPad *collect_pad;
GstClockTime min_duration; /* observed minimum duration */
collect_pad = (GstMatroskaPad *) collected->data;
@ -1650,6 +1739,13 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
gst_guint64_to_gdouble (duration) /
gst_guint64_to_gdouble (mux->time_scale));
gst_ebml_write_seek (ebml, pos);
} else {
/* void'ify */
guint64 my_pos = ebml->pos;
gst_ebml_write_seek (ebml, mux->duration_pos);
gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
gst_ebml_write_seek (ebml, my_pos);
}
/* finish segment - this also writes element length */
@ -1671,6 +1767,7 @@ static GstMatroskaPad *
gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
{
GSList *collected;
GstMatroskaPad *best = NULL;
*popped = FALSE;
@ -1743,12 +1840,19 @@ static GstFlowReturn
gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
{
GstEbmlWrite *ebml = mux->ebml_write;
GstBuffer *buf, *hdr;
guint64 cluster, blockgroup;
gboolean write_duration;
gint16 relative_timestamp;
gint64 relative_timestamp64;
guint64 block_duration;
gboolean is_video_keyframe = FALSE;
/* write data */
@ -1765,6 +1869,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
/* hm, invalid timestamp (due to --to be fixed--- element upstream);
* this would wreak havoc with time stored in matroska file */
/* TODO: maybe calculate a timestamp by using the previous timestamp
* and default duration */
if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
GST_WARNING_OBJECT (collect_pad->collect.pad,
"Invalid buffer timestamp; dropping buffer");
@ -1871,7 +1977,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
/* write the block, for matroska v2 use SimpleBlock if possible
* one slice (*breath*).
* FIXME: lacing, etc. */
* FIXME: Need to do correct lacing! */
relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
if (relative_timestamp64 >= 0) {
/* round the timestamp */
@ -1926,8 +2032,11 @@ static GstFlowReturn
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
{
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
GstMatroskaPad *best;
gboolean popped;
GstFlowReturn ret;
GST_DEBUG_OBJECT (mux, "Collected pads");
@ -1965,6 +2074,7 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
* the actual duration later when we send an updated header on eos */
if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
GstClockTime end_ts = start_ts;
if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
@ -2001,6 +2111,7 @@ static GstStateChangeReturn
gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
switch (transition) {
@ -2051,7 +2162,7 @@ gst_matroska_mux_set_property (GObject * object,
break;
}
g_free (mux->writing_app);
mux->writing_app = g_strdup (g_value_get_string (value));
mux->writing_app = g_value_dup_string (value);
break;
case ARG_MATROSKA_VERSION:
mux->matroska_version = g_value_get_int (value);