mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 11:32:38 +00:00
ext/ffmpeg/: Add GIF (animations and single images) decoding and encoding support.
Original commit message from CVS: * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps), (gst_ffmpeg_formatid_get_codecids), (gst_ffmpeg_get_codecid_longname): * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop), (gst_ffmpegdemux_register): * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_collected), (gst_ffmpegmux_register): Add GIF (animations and single images) decoding and encoding support. Fixes #503249.
This commit is contained in:
parent
f6186655c5
commit
a0bae2f656
5 changed files with 115 additions and 18 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2007-12-17 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
||||
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
|
||||
(gst_ffmpeg_formatid_get_codecids),
|
||||
(gst_ffmpeg_get_codecid_longname):
|
||||
* ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop),
|
||||
(gst_ffmpegdemux_register):
|
||||
* ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_collected),
|
||||
(gst_ffmpegmux_register):
|
||||
Add GIF (animations and single images) decoding and encoding support.
|
||||
Fixes #503249.
|
||||
|
||||
2007-12-17 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||
|
||||
* configure.ac:
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit a00d4c1966aab517c2694c61d580489ebcbce448
|
||||
Subproject commit 208ef72f86e944e6ba6941c68e57ffcea8d2a8f4
|
|
@ -636,8 +636,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
|
|||
break;
|
||||
case CODEC_ID_VC1:
|
||||
caps = gst_ff_vid_caps_new (context, codec_id, "video/x-wmv",
|
||||
"wmvversion", G_TYPE_INT, 3, "fourcc", GST_TYPE_FOURCC,
|
||||
GST_MAKE_FOURCC('W', 'V', 'C', '1'), NULL);
|
||||
"wmvversion", G_TYPE_INT, 3, "fourcc", GST_TYPE_FOURCC,
|
||||
GST_MAKE_FOURCC ('W', 'V', 'C', '1'), NULL);
|
||||
break;
|
||||
case CODEC_ID_QDM2:
|
||||
caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-qdm2", NULL);
|
||||
|
@ -683,6 +683,10 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
|
|||
caps = gst_ff_vid_caps_new (context, codec_id, "video/x-nuv", NULL);
|
||||
break;
|
||||
|
||||
case CODEC_ID_GIF:
|
||||
caps = gst_ff_vid_caps_new (context, codec_id, "image/gif", NULL);
|
||||
break;
|
||||
|
||||
case CODEC_ID_PNG:
|
||||
caps = gst_ff_vid_caps_new (context, codec_id, "image/png", NULL);
|
||||
break;
|
||||
|
@ -1914,6 +1918,12 @@ gst_ffmpeg_formatid_get_codecids (const gchar * format_name,
|
|||
};
|
||||
*video_codec_list = NULL;
|
||||
*audio_codec_list = amr_audio_list;
|
||||
} else if (!strcmp (format_name, "gif")) {
|
||||
static enum CodecID gif_image_list[] = {
|
||||
CODEC_ID_RAWVIDEO, CODEC_ID_NONE
|
||||
};
|
||||
*video_codec_list = gif_image_list;
|
||||
*audio_codec_list = NULL;
|
||||
} else {
|
||||
GST_LOG ("Format %s not found", format_name);
|
||||
return FALSE;
|
||||
|
@ -2055,14 +2065,15 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context)
|
|||
id = CODEC_ID_WMV2;
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
guint32 fourcc;
|
||||
if (gst_structure_get_fourcc (structure, "fourcc", &fourcc)) {
|
||||
if (fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1'))
|
||||
id = CODEC_ID_VC1;
|
||||
} else
|
||||
id = CODEC_ID_WMV3;
|
||||
}
|
||||
{
|
||||
guint32 fourcc;
|
||||
|
||||
if (gst_structure_get_fourcc (structure, "fourcc", &fourcc)) {
|
||||
if (fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1'))
|
||||
id = CODEC_ID_VC1;
|
||||
} else
|
||||
id = CODEC_ID_WMV3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2726,6 +2737,9 @@ gst_ffmpeg_get_codecid_longname (enum CodecID codec_id)
|
|||
case CODEC_ID_XVID:
|
||||
name = "XviD video";
|
||||
break;
|
||||
case CODEC_ID_GIF:
|
||||
name = "GIF image";
|
||||
break;
|
||||
case CODEC_ID_PNG:
|
||||
name = "PNG image";
|
||||
break;
|
||||
|
|
|
@ -1162,6 +1162,8 @@ gst_ffmpegdemux_loop (GstPad * pad)
|
|||
AVStream *avstream;
|
||||
GstBuffer *outbuf;
|
||||
GstClockTime timestamp, duration;
|
||||
gint outsize;
|
||||
gboolean rawvideo;
|
||||
|
||||
demux = (GstFFMpegDemux *) (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -1222,16 +1224,52 @@ gst_ffmpegdemux_loop (GstPad * pad)
|
|||
/* prepare to push packet to peer */
|
||||
srcpad = stream->pad;
|
||||
|
||||
rawvideo = (avstream->codec->codec_type == CODEC_TYPE_VIDEO &&
|
||||
avstream->codec->codec_id == CODEC_ID_RAWVIDEO);
|
||||
|
||||
if (rawvideo)
|
||||
outsize = gst_ffmpeg_avpicture_get_size (avstream->codec->pix_fmt,
|
||||
avstream->codec->width, avstream->codec->height);
|
||||
else
|
||||
outsize = pkt.size;
|
||||
|
||||
ret = gst_pad_alloc_buffer_and_set_caps (srcpad,
|
||||
GST_CLOCK_TIME_NONE, pkt.size, GST_PAD_CAPS (srcpad), &outbuf);
|
||||
GST_CLOCK_TIME_NONE, outsize, GST_PAD_CAPS (srcpad), &outbuf);
|
||||
/* we can ignore not linked */
|
||||
if (ret == GST_FLOW_NOT_LINKED)
|
||||
goto done;
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto no_buffer;
|
||||
|
||||
/* copy the data from packet into the target buffer */
|
||||
memcpy (GST_BUFFER_DATA (outbuf), pkt.data, pkt.size);
|
||||
/* copy the data from packet into the target buffer
|
||||
* and do conversions for raw video packets */
|
||||
if (rawvideo) {
|
||||
AVPicture src, dst;
|
||||
const gchar *plugin_name =
|
||||
((GstFFMpegDemuxClass *) (G_OBJECT_GET_CLASS (demux)))->in_plugin->name;
|
||||
|
||||
if (strcmp (plugin_name, "gif") == 0) {
|
||||
src.data[0] = pkt.data;
|
||||
src.data[1] = NULL;
|
||||
src.data[2] = NULL;
|
||||
src.linesize[0] = avstream->codec->width * 3;;
|
||||
} else {
|
||||
GST_WARNING ("Unknown demuxer %s, no idea what to do", plugin_name);
|
||||
gst_ffmpeg_avpicture_fill (&src, pkt.data,
|
||||
avstream->codec->pix_fmt, avstream->codec->width,
|
||||
avstream->codec->height);
|
||||
}
|
||||
|
||||
gst_ffmpeg_avpicture_fill (&dst, GST_BUFFER_DATA (outbuf),
|
||||
avstream->codec->pix_fmt, avstream->codec->width,
|
||||
avstream->codec->height);
|
||||
|
||||
gst_ffmpeg_img_convert (&dst, avstream->codec->pix_fmt,
|
||||
&src, avstream->codec->pix_fmt, avstream->codec->width,
|
||||
avstream->codec->height);
|
||||
} else {
|
||||
memcpy (GST_BUFFER_DATA (outbuf), pkt.data, outsize);
|
||||
}
|
||||
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||
GST_BUFFER_DURATION (outbuf) = duration;
|
||||
|
@ -1498,7 +1536,8 @@ gst_ffmpegdemux_register (GstPlugin * plugin)
|
|||
!strcmp (in_plugin->name, "wav") ||
|
||||
!strcmp (in_plugin->name, "au") ||
|
||||
!strcmp (in_plugin->name, "tta") ||
|
||||
!strcmp (in_plugin->name, "rm") || !strcmp (in_plugin->name, "amr"))
|
||||
!strcmp (in_plugin->name, "rm") ||
|
||||
!strcmp (in_plugin->name, "amr") || !strcmp (in_plugin->name, "gif"))
|
||||
register_typefind_func = FALSE;
|
||||
|
||||
/* Set the rank of demuxers know to work to MARGINAL.
|
||||
|
@ -1533,7 +1572,8 @@ gst_ffmpegdemux_register (GstPlugin * plugin)
|
|||
!strcmp (in_plugin->name, "avs") ||
|
||||
!strcmp (in_plugin->name, "aiff") ||
|
||||
!strcmp (in_plugin->name, "4xm") ||
|
||||
!strcmp (in_plugin->name, "yuv4mpegpipe"))
|
||||
!strcmp (in_plugin->name, "yuv4mpegpipe") ||
|
||||
!strcmp (in_plugin->name, "gif"))
|
||||
rank = GST_RANK_MARGINAL;
|
||||
else
|
||||
rank = GST_RANK_NONE;
|
||||
|
|
|
@ -525,6 +525,7 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
if (best_pad != NULL) {
|
||||
GstBuffer *buf;
|
||||
AVPacket pkt;
|
||||
gboolean need_free = FALSE;
|
||||
|
||||
/* push out current buffer */
|
||||
buf = gst_collect_pads_pop (ffmpegmux->collect,
|
||||
|
@ -536,8 +537,30 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
pkt.pts = gst_ffmpeg_time_gst_to_ff (GST_BUFFER_TIMESTAMP (buf),
|
||||
ffmpegmux->context->streams[best_pad->padnum]->time_base);
|
||||
pkt.dts = pkt.pts;
|
||||
pkt.data = GST_BUFFER_DATA (buf);
|
||||
pkt.size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
if (strcmp (ffmpegmux->context->oformat->name, "gif") == 0) {
|
||||
AVStream *st = ffmpegmux->context->streams[best_pad->padnum];
|
||||
AVPicture src, dst;
|
||||
|
||||
need_free = TRUE;
|
||||
pkt.size = st->codec->width * st->codec->height * 3;
|
||||
pkt.data = g_malloc (pkt.size);
|
||||
|
||||
dst.data[0] = pkt.data;
|
||||
dst.data[1] = NULL;
|
||||
dst.data[2] = NULL;
|
||||
dst.linesize[0] = st->codec->width * 3;
|
||||
|
||||
gst_ffmpeg_avpicture_fill (&src, GST_BUFFER_DATA (buf),
|
||||
PIX_FMT_RGB24, st->codec->width, st->codec->height);
|
||||
|
||||
gst_ffmpeg_img_convert (&dst, PIX_FMT_RGB24,
|
||||
&src, PIX_FMT_RGB24, st->codec->width, st->codec->height);
|
||||
} else {
|
||||
pkt.data = GST_BUFFER_DATA (buf);
|
||||
pkt.size = GST_BUFFER_SIZE (buf);
|
||||
}
|
||||
|
||||
pkt.stream_index = best_pad->padnum;
|
||||
pkt.flags = 0;
|
||||
|
||||
|
@ -552,6 +575,8 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
pkt.duration = 0;
|
||||
av_write_frame (ffmpegmux->context, &pkt);
|
||||
gst_buffer_unref (buf);
|
||||
if (need_free)
|
||||
g_free (pkt.data);
|
||||
} else {
|
||||
/* close down */
|
||||
av_write_trailer (ffmpegmux->context);
|
||||
|
@ -725,6 +750,12 @@ gst_ffmpegmux_register (GstPlugin * plugin)
|
|||
const gint rates[] = { 44100, 22050, 11025 };
|
||||
|
||||
gst_ffmpeg_mux_simple_caps_set_int_list (audiosinkcaps, "rate", 3, rates);
|
||||
} else if (strcmp (in_plugin->name, "gif") == 0) {
|
||||
if (videosinkcaps)
|
||||
gst_caps_unref (videosinkcaps);
|
||||
|
||||
videosinkcaps =
|
||||
gst_caps_from_string ("video/x-raw-rgb, bpp=(int)24, depth=(int)24");
|
||||
}
|
||||
|
||||
/* create a cache for these properties */
|
||||
|
|
Loading…
Reference in a new issue