mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-26 01:02:33 +00:00
avformat/microdvd: export the declared frame rate
MicroDVD files are normally frame-based (i.e. there are no absolute timestamps), but can have an optional frame rate header. If this header is missing, the timestamps depend on the frame rate of the video they were created for. The demuxer will use a fallback frame rate if it's missing from the header. Currently, applications using libavformat can't know whether the time base is based on the fallback value, or if a frame rate header was present. This commit introduces a subfps AVOption for MicroDVD, and the demuxer sets it if and only if a frame rate header was present. Signed-off-by: Clément Bœsch <u@pkh.me>
This commit is contained in:
parent
0786598f51
commit
b416517cce
@ -24,12 +24,15 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "subtitles.h"
|
#include "subtitles.h"
|
||||||
#include "libavutil/intreadwrite.h"
|
#include "libavutil/intreadwrite.h"
|
||||||
|
#include "libavutil/opt.h"
|
||||||
|
|
||||||
#define MAX_LINESIZE 2048
|
#define MAX_LINESIZE 2048
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
const AVClass *class;
|
||||||
FFDemuxSubtitlesQueue q;
|
FFDemuxSubtitlesQueue q;
|
||||||
|
AVRational frame_rate;
|
||||||
} MicroDVDContext;
|
} MicroDVDContext;
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +83,7 @@ static int microdvd_read_header(AVFormatContext *s)
|
|||||||
AVStream *st = avformat_new_stream(s, NULL);
|
AVStream *st = avformat_new_stream(s, NULL);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char line_buf[MAX_LINESIZE];
|
char line_buf[MAX_LINESIZE];
|
||||||
|
int has_real_fps = 0;
|
||||||
|
|
||||||
if (!st)
|
if (!st)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
@ -105,8 +109,10 @@ static int microdvd_read_header(AVFormatContext *s)
|
|||||||
|
|
||||||
if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 ||
|
if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 ||
|
||||||
sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2)
|
sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2)
|
||||||
&& frame <= 1 && fps > 3 && fps < 100)
|
&& frame <= 1 && fps > 3 && fps < 100) {
|
||||||
pts_info = av_d2q(fps, 100000);
|
pts_info = av_d2q(fps, 100000);
|
||||||
|
has_real_fps = 1;
|
||||||
|
}
|
||||||
if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) {
|
if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) {
|
||||||
st->codec->extradata = av_strdup(line + 11);
|
st->codec->extradata = av_strdup(line + 11);
|
||||||
if (!st->codec->extradata)
|
if (!st->codec->extradata)
|
||||||
@ -135,6 +141,13 @@ static int microdvd_read_header(AVFormatContext *s)
|
|||||||
sub->duration = get_duration(line);
|
sub->duration = get_duration(line);
|
||||||
}
|
}
|
||||||
ff_subtitles_queue_finalize(µdvd->q);
|
ff_subtitles_queue_finalize(µdvd->q);
|
||||||
|
if (has_real_fps) {
|
||||||
|
/* export the FPS info only if set in the file */
|
||||||
|
microdvd->frame_rate = pts_info;
|
||||||
|
} else if (microdvd->frame_rate.num) {
|
||||||
|
/* fallback on user specified frame rate */
|
||||||
|
pts_info = microdvd->frame_rate;
|
||||||
|
}
|
||||||
avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num);
|
avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num);
|
||||||
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
|
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
|
||||||
st->codec->codec_id = AV_CODEC_ID_MICRODVD;
|
st->codec->codec_id = AV_CODEC_ID_MICRODVD;
|
||||||
@ -162,6 +175,21 @@ static int microdvd_read_close(AVFormatContext *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define OFFSET(x) offsetof(MicroDVDContext, x)
|
||||||
|
#define SD AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM
|
||||||
|
static const AVOption microdvd_options[] = {
|
||||||
|
{ "subfps", "set the movie frame rate fallback", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, SD },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const AVClass microdvd_class = {
|
||||||
|
.class_name = "microdvddec",
|
||||||
|
.item_name = av_default_item_name,
|
||||||
|
.option = microdvd_options,
|
||||||
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
|
};
|
||||||
|
|
||||||
AVInputFormat ff_microdvd_demuxer = {
|
AVInputFormat ff_microdvd_demuxer = {
|
||||||
.name = "microdvd",
|
.name = "microdvd",
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
|
.long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
|
||||||
@ -171,4 +199,5 @@ AVInputFormat ff_microdvd_demuxer = {
|
|||||||
.read_packet = microdvd_read_packet,
|
.read_packet = microdvd_read_packet,
|
||||||
.read_seek2 = microdvd_read_seek,
|
.read_seek2 = microdvd_read_seek,
|
||||||
.read_close = microdvd_read_close,
|
.read_close = microdvd_read_close,
|
||||||
|
.priv_class = µdvd_class,
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#define LIBAVFORMAT_VERSION_MAJOR 55
|
#define LIBAVFORMAT_VERSION_MAJOR 55
|
||||||
#define LIBAVFORMAT_VERSION_MINOR 33
|
#define LIBAVFORMAT_VERSION_MINOR 33
|
||||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
#define LIBAVFORMAT_VERSION_MICRO 101
|
||||||
|
|
||||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||||
LIBAVFORMAT_VERSION_MINOR, \
|
LIBAVFORMAT_VERSION_MINOR, \
|
||||||
|
Loading…
Reference in New Issue
Block a user