summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2008-12-16 15:11:33 +0100
committerBenjamin Otte <otte@gnome.org>2008-12-16 15:11:33 +0100
commitf82ce694440e90e783af8f90e8e3f8bb9382bf66 (patch)
tree692fe2ff8c2aff194e19b7c8dae30aac5ec15cbc
parent6438ee54032919a9c7789881604a0bb2739a688c (diff)
parent08ed13b0f846815735eb6a29af2dc4b6d53bc969 (diff)
Merge branch '0.8'
-rw-r--r--swfdec/swfdec_audio_decoder.c31
-rw-r--r--swfdec/swfdec_audio_decoder.h6
-rw-r--r--swfdec/swfdec_audio_decoder_gst.c18
-rw-r--r--swfdec/swfdec_audio_flv.c43
-rw-r--r--swfdec/swfdec_codec_gst.c18
-rw-r--r--swfdec/swfdec_codec_gst.h3
-rw-r--r--swfdec/swfdec_net_stream.c44
-rw-r--r--swfdec/swfdec_video_decoder.c32
-rw-r--r--swfdec/swfdec_video_decoder.h7
-rw-r--r--swfdec/swfdec_video_decoder_gst.c19
10 files changed, 209 insertions, 12 deletions
diff --git a/swfdec/swfdec_audio_decoder.c b/swfdec/swfdec_audio_decoder.c
index 72be7326..c1dbf605 100644
--- a/swfdec/swfdec_audio_decoder.c
+++ b/swfdec/swfdec_audio_decoder.c
@@ -28,8 +28,17 @@
G_DEFINE_TYPE (SwfdecAudioDecoder, swfdec_audio_decoder, G_TYPE_OBJECT)
static void
+swfdec_audio_decoder_do_set_codec_data (SwfdecAudioDecoder *decoder,
+ SwfdecBuffer *buffer)
+{
+ SWFDEC_WARNING ("%s does not implement codec data",
+ G_OBJECT_TYPE_NAME (decoder));
+}
+
+static void
swfdec_audio_decoder_class_init (SwfdecAudioDecoderClass *klass)
{
+ klass->set_codec_data = swfdec_audio_decoder_do_set_codec_data;
}
static void
@@ -117,6 +126,28 @@ swfdec_audio_decoder_new (guint codec, SwfdecAudioFormat format)
}
/**
+ * swfdec_audio_decoder_set_codec_data:
+ * @decoder: an audio decoder
+ * @buffer: setup data for the decoder. May be %NULL
+ *
+ * Provides setup data for the audio decoder. This function is usually called
+ * on initialization, but can be called at any time. Currently this
+ * functionality is only used for AAC audio.
+ **/
+void
+swfdec_audio_decoder_set_codec_data (SwfdecAudioDecoder *decoder, SwfdecBuffer *buffer)
+{
+ SwfdecAudioDecoderClass *klass;
+
+ g_return_if_fail (SWFDEC_IS_AUDIO_DECODER (decoder));
+
+ if (decoder->error)
+ return;
+ klass = SWFDEC_AUDIO_DECODER_GET_CLASS (decoder);
+ klass->set_codec_data (decoder, buffer);
+}
+
+/**
* swfdec_audio_decoder_push:
* @decoder: a #SwfdecAudioDecoder
* @buffer: a #SwfdecBuffer to process or %NULL to flush
diff --git a/swfdec/swfdec_audio_decoder.h b/swfdec/swfdec_audio_decoder.h
index 6837a48a..ee72d3ed 100644
--- a/swfdec/swfdec_audio_decoder.h
+++ b/swfdec/swfdec_audio_decoder.h
@@ -72,6 +72,9 @@ struct _SwfdecAudioDecoderClass
SwfdecAudioDecoder * (* create) (guint codec,
SwfdecAudioFormat format);
+ void (* set_codec_data)
+ (SwfdecAudioDecoder * decoder,
+ SwfdecBuffer * buffer);
void (* push) (SwfdecAudioDecoder * decoder,
SwfdecBuffer * buffer);
SwfdecBuffer * (* pull) (SwfdecAudioDecoder * decoder);
@@ -87,6 +90,9 @@ gboolean swfdec_audio_decoder_prepare (guint codec,
SwfdecAudioDecoder * swfdec_audio_decoder_new (guint codec,
SwfdecAudioFormat format);
+void swfdec_audio_decoder_set_codec_data
+ (SwfdecAudioDecoder * decoder,
+ SwfdecBuffer * buffer);
void swfdec_audio_decoder_push (SwfdecAudioDecoder * decoder,
SwfdecBuffer * buffer);
SwfdecBuffer * swfdec_audio_decoder_pull (SwfdecAudioDecoder * decoder);
diff --git a/swfdec/swfdec_audio_decoder_gst.c b/swfdec/swfdec_audio_decoder_gst.c
index 9b29957f..7354d72e 100644
--- a/swfdec/swfdec_audio_decoder_gst.c
+++ b/swfdec/swfdec_audio_decoder_gst.c
@@ -47,6 +47,9 @@ swfdec_audio_decoder_get_caps (guint codec, SwfdecAudioFormat format)
swfdec_audio_format_get_rate (format),
swfdec_audio_format_get_channels (format));
break;
+ case SWFDEC_AUDIO_CODEC_AAC:
+ s = g_strdup_printf ("audio/mpeg, mpegversion=4");
+ break;
default:
return NULL;
}
@@ -142,6 +145,20 @@ error:
}
static void
+swfdec_audio_decoder_gst_set_codec_data (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
+{
+ SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
+
+ if (buffer) {
+ GstBuffer *buf = swfdec_gst_buffer_new (swfdec_buffer_ref (buffer));
+ swfdec_gst_decoder_set_codec_data (&player->dec, buf);
+ gst_buffer_unref (buf);
+ } else {
+ swfdec_gst_decoder_set_codec_data (&player->dec, NULL);
+ }
+}
+
+static void
swfdec_audio_decoder_gst_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
{
SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
@@ -189,6 +206,7 @@ swfdec_audio_decoder_gst_class_init (SwfdecAudioDecoderGstClass *klass)
decoder_class->prepare = swfdec_audio_decoder_gst_prepare;
decoder_class->create = swfdec_audio_decoder_gst_create;
+ decoder_class->set_codec_data = swfdec_audio_decoder_gst_set_codec_data;
decoder_class->pull = swfdec_audio_decoder_gst_pull;
decoder_class->push = swfdec_audio_decoder_gst_push;
}
diff --git a/swfdec/swfdec_audio_flv.c b/swfdec/swfdec_audio_flv.c
index 2a49ee6e..4595f074 100644
--- a/swfdec/swfdec_audio_flv.c
+++ b/swfdec/swfdec_audio_flv.c
@@ -95,6 +95,18 @@ swfdec_audio_flv_decode_one (SwfdecAudioFlv *flv)
flv->decoder = swfdec_audio_decoder_new (flv->format, flv->in);
if (flv->decoder == NULL)
return NULL;
+ /* This is a hack that ensures AAC codec data is always present, even if
+ * the decoder gets initialized in the middle of the stream */
+ if (format == SWFDEC_AUDIO_CODEC_AAC) {
+ SwfdecBuffer *tmp = swfdec_flv_decoder_get_audio (flv->flvdecoder,
+ 0, &format, NULL, NULL, NULL);
+ if (format == SWFDEC_AUDIO_CODEC_AAC && tmp->data[0] == 0 &&
+ tmp->length > 1) {
+ tmp = swfdec_buffer_new_subbuffer (tmp, 1, tmp->length - 1);
+ swfdec_audio_decoder_set_codec_data (flv->decoder, tmp);
+ swfdec_buffer_unref (tmp);
+ }
+ }
} else if (format != flv->format ||
in != flv->in) {
SWFDEC_ERROR ("FIXME: format change not implemented");
@@ -102,7 +114,36 @@ swfdec_audio_flv_decode_one (SwfdecAudioFlv *flv)
} else if (flv->decoder == NULL) {
return NULL;
}
- swfdec_audio_decoder_push (flv->decoder, buffer);
+ if (format == SWFDEC_AUDIO_CODEC_AAC) {
+ SwfdecBuffer *data;
+ SwfdecBits bits;
+ guint type;
+ swfdec_bits_init (&bits, buffer);
+ type = swfdec_bits_get_u8 (&bits);
+ switch (type) {
+ case 0:
+ data = swfdec_bits_get_buffer (&bits, -1);
+ if (data) {
+ swfdec_audio_decoder_set_codec_data (flv->decoder, data);
+ swfdec_buffer_unref (data);
+ }
+ break;
+ case 1:
+ data = swfdec_bits_get_buffer (&bits, -1);
+ if (data) {
+ swfdec_audio_decoder_push (flv->decoder, data);
+ swfdec_buffer_unref (data);
+ } else {
+ SWFDEC_ERROR ("no data in AAC data buffer?");
+ }
+ break;
+ default:
+ SWFDEC_FIXME ("handle AAC type %u", type);
+ break;
+ }
+ } else {
+ swfdec_audio_decoder_push (flv->decoder, buffer);
+ }
if (flv->next_timestamp == 0)
swfdec_audio_decoder_push (flv->decoder, NULL);
buffer = swfdec_audio_decoder_pull (flv->decoder);
diff --git a/swfdec/swfdec_codec_gst.c b/swfdec/swfdec_codec_gst.c
index 638e8a6e..4eef8d93 100644
--- a/swfdec/swfdec_codec_gst.c
+++ b/swfdec/swfdec_codec_gst.c
@@ -271,6 +271,24 @@ swfdec_gst_decoder_finish (SwfdecGstDecoder *dec)
}
}
+void
+swfdec_gst_decoder_set_codec_data (SwfdecGstDecoder *dec,
+ GstBuffer *buffer)
+{
+ GstCaps *caps;
+
+ caps = gst_pad_get_caps (dec->src);
+ caps = gst_caps_make_writable (caps);
+ if (buffer) {
+ gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL);
+ } else {
+ GstStructure *structure = gst_caps_get_structure (caps, 0);
+ gst_structure_remove_field (structure, "codec_data");
+ }
+ gst_pad_set_caps (dec->src, caps);
+ gst_caps_unref (caps);
+}
+
gboolean
swfdec_gst_decoder_push (SwfdecGstDecoder *dec, GstBuffer *buffer)
{
diff --git a/swfdec/swfdec_codec_gst.h b/swfdec/swfdec_codec_gst.h
index 049422d8..31e83195 100644
--- a/swfdec/swfdec_codec_gst.h
+++ b/swfdec/swfdec_codec_gst.h
@@ -38,6 +38,9 @@ gboolean swfdec_gst_decoder_init (SwfdecGstDecoder * dec,
GstCaps * srccaps,
GstCaps * sinkcaps,
...) G_GNUC_NULL_TERMINATED;
+void swfdec_gst_decoder_set_codec_data
+ (SwfdecGstDecoder * dec,
+ GstBuffer * buffer);
void swfdec_gst_decoder_push_eos (SwfdecGstDecoder * dec);
GstBuffer * swfdec_gst_decoder_pull (SwfdecGstDecoder * dec);
gboolean swfdec_gst_decoder_push (SwfdecGstDecoder * dec,
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index 7472b560..a3ce7162 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -103,6 +103,35 @@ swfdec_net_stream_decode_video (SwfdecVideoDecoder *decoder, SwfdecBuffer *buffe
decoder->width -= wsub;
decoder->height -= hsub;
}
+ } else if (decoder->codec == SWFDEC_VIDEO_CODEC_H264) {
+ SwfdecBits bits;
+ guint type;
+ SwfdecBuffer *data;
+ swfdec_bits_init (&bits, buffer);
+ type = swfdec_bits_get_u8 (&bits);
+ /* composition_time_offset = */ swfdec_bits_get_bu24 (&bits);
+ switch (type) {
+ case 0:
+ data = swfdec_bits_get_buffer (&bits, -1);
+ if (data) {
+ swfdec_video_decoder_set_codec_data (decoder, data);
+ swfdec_buffer_unref (data);
+ }
+ break;
+ case 1:
+ data = swfdec_bits_get_buffer (&bits, -1);
+ if (data) {
+ swfdec_video_decoder_decode (decoder, data);
+ } else {
+ SWFDEC_ERROR ("no data in H264 buffer?");
+ }
+ break;
+ case 2:
+ break;
+ default:
+ SWFDEC_ERROR ("H264 data type %u not supported", type);
+ break;
+ }
} else {
swfdec_video_decoder_decode (decoder, buffer);
}
@@ -139,14 +168,11 @@ swfdec_net_stream_video_goto (SwfdecNetStream *stream, guint timestamp)
} else {
guint next;
- if (stream->decoder && swfdec_video_decoder_get_codec (stream->decoder) != format) {
- g_object_unref (stream->decoder);
- stream->decoder = NULL;
- }
if (stream->decoder != NULL &&
- (stream->decoder_time >= stream->current_time)) {
- g_object_unref (stream->decoder);
- stream->decoder = NULL;
+ stream->decoder_time >= stream->current_time) {
+ buffer = swfdec_flv_decoder_get_video (stream->flvdecoder,
+ stream->current_time, TRUE, &format, &stream->decoder_time,
+ &next);
}
if (stream->decoder == NULL) {
@@ -641,10 +667,6 @@ swfdec_net_stream_seek (SwfdecNetStream *stream, double secs)
SWFDEC_ERROR ("FIXME: implement seeking in audio only NetStream");
return;
}
- if (stream->decoder) {
- g_object_unref (stream->decoder);
- stream->decoder = NULL;
- }
msecs = secs * 1000;
msecs += first;
if (msecs > last)
diff --git a/swfdec/swfdec_video_decoder.c b/swfdec/swfdec_video_decoder.c
index c09a2930..527ac1e0 100644
--- a/swfdec/swfdec_video_decoder.c
+++ b/swfdec/swfdec_video_decoder.c
@@ -30,8 +30,17 @@
G_DEFINE_TYPE (SwfdecVideoDecoder, swfdec_video_decoder, G_TYPE_OBJECT)
static void
+swfdec_video_decoder_do_set_codec_data (SwfdecVideoDecoder *decoder,
+ SwfdecBuffer *buffer)
+{
+ SWFDEC_WARNING ("%s does not implement codec data",
+ G_OBJECT_TYPE_NAME (decoder));
+}
+
+static void
swfdec_video_decoder_class_init (SwfdecVideoDecoderClass *klass)
{
+ klass->set_codec_data = swfdec_video_decoder_do_set_codec_data;
}
static void
@@ -65,6 +74,7 @@ swfdec_video_codec_get_format (guint codec)
case SWFDEC_VIDEO_CODEC_H263:
case SWFDEC_VIDEO_CODEC_VP6:
case SWFDEC_VIDEO_CODEC_VP6_ALPHA:
+ case SWFDEC_VIDEO_CODEC_H264:
return SWFDEC_VIDEO_FORMAT_I420;
case SWFDEC_VIDEO_CODEC_UNDEFINED:
case SWFDEC_VIDEO_CODEC_SCREEN:
@@ -142,6 +152,28 @@ swfdec_video_decoder_new (guint codec)
}
/**
+ * swfdec_video_decoder_set_codec_data:
+ * @decoder: a video decoder
+ * @buffer: setup data for the decoder. May be %NULL
+ *
+ * Provides setup data for the video decoder. This function is usually called
+ * on initialization, but can be called at any time. Currently this
+ * functionality is only used for H264.
+ **/
+void
+swfdec_video_decoder_set_codec_data (SwfdecVideoDecoder *decoder, SwfdecBuffer *buffer)
+{
+ SwfdecVideoDecoderClass *klass;
+
+ g_return_if_fail (SWFDEC_IS_VIDEO_DECODER (decoder));
+
+ if (decoder->error)
+ return;
+ klass = SWFDEC_VIDEO_DECODER_GET_CLASS (decoder);
+ klass->set_codec_data (decoder, buffer);
+}
+
+/**
* swfdec_video_decoder_decode:
* @decoder: a #SwfdecVideoDecoder
* @buffer: a #SwfdecBuffer to process
diff --git a/swfdec/swfdec_video_decoder.h b/swfdec/swfdec_video_decoder.h
index 2b1b6636..21248fab 100644
--- a/swfdec/swfdec_video_decoder.h
+++ b/swfdec/swfdec_video_decoder.h
@@ -32,6 +32,7 @@ G_BEGIN_DECLS
#define SWFDEC_VIDEO_CODEC_VP6 4
#define SWFDEC_VIDEO_CODEC_VP6_ALPHA 5
#define SWFDEC_VIDEO_CODEC_SCREEN2 6
+#define SWFDEC_VIDEO_CODEC_H264 7
typedef enum {
SWFDEC_VIDEO_FORMAT_RGBA,
@@ -75,6 +76,9 @@ struct _SwfdecVideoDecoderClass
char ** missing);
SwfdecVideoDecoder * (* create) (guint codec);
+ void (* set_codec_data)
+ (SwfdecVideoDecoder * decoder,
+ SwfdecBuffer * buffer);
void (* decode) (SwfdecVideoDecoder * decoder,
SwfdecBuffer * buffer);
};
@@ -90,6 +94,9 @@ gboolean swfdec_video_decoder_prepare (guint codec,
SwfdecVideoDecoder * swfdec_video_decoder_new (guint codec);
+void swfdec_video_decoder_set_codec_data
+ (SwfdecVideoDecoder * decoder,
+ SwfdecBuffer * buffer);
void swfdec_video_decoder_decode (SwfdecVideoDecoder * decoder,
SwfdecBuffer * buffer);
guint swfdec_video_decoder_get_codec (SwfdecVideoDecoder * decoder);
diff --git a/swfdec/swfdec_video_decoder_gst.c b/swfdec/swfdec_video_decoder_gst.c
index 893fc450..07f48284 100644
--- a/swfdec/swfdec_video_decoder_gst.c
+++ b/swfdec/swfdec_video_decoder_gst.c
@@ -40,6 +40,9 @@ swfdec_video_decoder_get_caps (guint codec)
case SWFDEC_VIDEO_CODEC_VP6:
caps = gst_caps_from_string ("video/x-vp6-flash");
break;
+ case SWFDEC_VIDEO_CODEC_H264:
+ caps = gst_caps_from_string ("video/x-h264");
+ break;
default:
return NULL;
}
@@ -119,6 +122,21 @@ swfdec_video_decoder_gst_create (guint codec)
}
static void
+swfdec_video_decoder_gst_set_codec_data (SwfdecVideoDecoder *dec,
+ SwfdecBuffer *buffer)
+{
+ SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (dec);
+
+ if (buffer) {
+ GstBuffer *buf = swfdec_gst_buffer_new (swfdec_buffer_ref (buffer));
+ swfdec_gst_decoder_set_codec_data (&player->dec, buf);
+ gst_buffer_unref (buf);
+ } else {
+ swfdec_gst_decoder_set_codec_data (&player->dec, NULL);
+ }
+}
+
+static void
swfdec_video_decoder_gst_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer)
{
SwfdecVideoDecoderGst *player = SWFDEC_VIDEO_DECODER_GST (dec);
@@ -201,6 +219,7 @@ swfdec_video_decoder_gst_class_init (SwfdecVideoDecoderGstClass *klass)
decoder_class->prepare = swfdec_video_decoder_gst_prepare;
decoder_class->create = swfdec_video_decoder_gst_create;
+ decoder_class->set_codec_data = swfdec_video_decoder_gst_set_codec_data;
decoder_class->decode = swfdec_video_decoder_gst_decode;
}