diff options
author | Benjamin Otte <otte@gnome.org> | 2008-12-16 15:11:33 +0100 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2008-12-16 15:11:33 +0100 |
commit | f82ce694440e90e783af8f90e8e3f8bb9382bf66 (patch) | |
tree | 692fe2ff8c2aff194e19b7c8dae30aac5ec15cbc | |
parent | 6438ee54032919a9c7789881604a0bb2739a688c (diff) | |
parent | 08ed13b0f846815735eb6a29af2dc4b6d53bc969 (diff) |
Merge branch '0.8'
-rw-r--r-- | swfdec/swfdec_audio_decoder.c | 31 | ||||
-rw-r--r-- | swfdec/swfdec_audio_decoder.h | 6 | ||||
-rw-r--r-- | swfdec/swfdec_audio_decoder_gst.c | 18 | ||||
-rw-r--r-- | swfdec/swfdec_audio_flv.c | 43 | ||||
-rw-r--r-- | swfdec/swfdec_codec_gst.c | 18 | ||||
-rw-r--r-- | swfdec/swfdec_codec_gst.h | 3 | ||||
-rw-r--r-- | swfdec/swfdec_net_stream.c | 44 | ||||
-rw-r--r-- | swfdec/swfdec_video_decoder.c | 32 | ||||
-rw-r--r-- | swfdec/swfdec_video_decoder.h | 7 | ||||
-rw-r--r-- | swfdec/swfdec_video_decoder_gst.c | 19 |
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; } |