Commit 0aa5a7b2 authored by Paul B Mahol's avatar Paul B Mahol

avformat/gifdec: export duration, nb_frames and comment

parent f2664a30
......@@ -43,6 +43,7 @@ static const uint8_t gif89a_sig[6] = "GIF89a";
#define GIF_EXTENSION_INTRODUCER 0x21
#define GIF_IMAGE_SEPARATOR 0x2c
#define GIF_GCE_EXT_LABEL 0xf9
#define GIF_COM_EXT_LABEL 0xfe
#define GIF_APP_EXT_LABEL 0xff
#define NETSCAPE_EXT_STR "NETSCAPE2.0"
......
......@@ -25,6 +25,7 @@
*/
#include "avformat.h"
#include "libavutil/bprint.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "internal.h"
......@@ -94,12 +95,25 @@ static int resync(AVIOContext *pb)
return 0;
}
static int gif_skip_subblocks(AVIOContext *pb)
{
int sb_size, ret = 0;
while (0x00 != (sb_size = avio_r8(pb))) {
if ((ret = avio_skip(pb, sb_size)) < 0)
return ret;
}
return ret;
}
static int gif_read_header(AVFormatContext *s)
{
GIFDemuxContext *gdc = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
int width, height, ret, n;
int type, width, height, ret, n, flags;
int64_t nb_frames = 0, duration = 0;
if ((ret = resync(pb)) < 0)
return ret;
......@@ -107,7 +121,8 @@ static int gif_read_header(AVFormatContext *s)
gdc->delay = gdc->default_delay;
width = avio_rl16(pb);
height = avio_rl16(pb);
avio_skip(pb, 2);
flags = avio_r8(pb);
avio_skip(pb, 1);
n = avio_r8(pb);
if (width == 0 || height == 0)
......@@ -117,6 +132,57 @@ static int gif_read_header(AVFormatContext *s)
if (!st)
return AVERROR(ENOMEM);
if (flags & 0x80)
avio_skip(pb, 3 * (1 << ((flags & 0x07) + 1)));
while ((type = avio_r8(pb)) != GIF_TRAILER) {
if (avio_feof(pb))
break;
if (type == GIF_EXTENSION_INTRODUCER) {
int subtype = avio_r8(pb);
if (subtype == GIF_COM_EXT_LABEL) {
AVBPrint bp;
int block_size;
av_bprint_init(&bp, 0, -1);
while ((block_size = avio_r8(pb)) != 0) {
avio_read_to_bprint(pb, &bp, block_size);
}
av_dict_set(&s->metadata, "comment", bp.str, 0);
av_bprint_finalize(&bp, NULL);
} else if (subtype == GIF_GCE_EXT_LABEL) {
int block_size = avio_r8(pb);
if (block_size == 4) {
int delay;
avio_skip(pb, 1);
delay = avio_rl16(pb);
if (delay < gdc->min_delay)
delay = gdc->default_delay;
delay = FFMIN(delay, gdc->max_delay);
duration += delay;
avio_skip(pb, 1);
} else {
avio_skip(pb, block_size);
}
gif_skip_subblocks(pb);
} else {
gif_skip_subblocks(pb);
}
} else if (type == GIF_IMAGE_SEPARATOR) {
avio_skip(pb, 8);
flags = avio_r8(pb);
if (flags & 0x80)
avio_skip(pb, 3 * (1 << ((flags & 0x07) + 1)));
avio_skip(pb, 1);
gif_skip_subblocks(pb);
nb_frames++;
} else {
break;
}
}
/* GIF format operates with time in "hundredths of second",
* therefore timebase is 1/100 */
avpriv_set_pts_info(st, 64, 1, 100);
......@@ -124,6 +190,9 @@ static int gif_read_header(AVFormatContext *s)
st->codecpar->codec_id = AV_CODEC_ID_GIF;
st->codecpar->width = width;
st->codecpar->height = height;
st->start_time = 0;
st->duration = duration;
st->nb_frames = nb_frames;
if (n) {
st->codecpar->sample_aspect_ratio.num = n + 15;
st->codecpar->sample_aspect_ratio.den = 64;
......@@ -136,18 +205,6 @@ static int gif_read_header(AVFormatContext *s)
return 0;
}
static int gif_skip_subblocks(AVIOContext *pb)
{
int sb_size, ret = 0;
while (0x00 != (sb_size = avio_r8(pb))) {
if ((ret = avio_skip(pb, sb_size)) < 0)
return ret;
}
return ret;
}
static int gif_read_ext(AVFormatContext *s)
{
GIFDemuxContext *gdc = s->priv_data;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment