mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
dv: add timecode to metadata
Reviewed-by: Reimar Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
a45880dcdb
commit
357cb53306
@ -7,6 +7,7 @@ version next:
|
|||||||
- SBaGen (SBG) binaural beats script demuxer
|
- SBaGen (SBG) binaural beats script demuxer
|
||||||
- OpenMG Audio muxer
|
- OpenMG Audio muxer
|
||||||
- SMJPEG demuxer
|
- SMJPEG demuxer
|
||||||
|
- dv: add timecode to metadata
|
||||||
|
|
||||||
|
|
||||||
version 0.9:
|
version 0.9:
|
||||||
|
@ -87,6 +87,9 @@ static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t)
|
|||||||
case dv_video_control:
|
case dv_video_control:
|
||||||
offs = (80*5 + 48 + 5);
|
offs = (80*5 + 48 + 5);
|
||||||
break;
|
break;
|
||||||
|
case dv_timecode:
|
||||||
|
offs = (80*1 + 3 + 3);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -267,6 +270,45 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bcd2int(uint8_t bcd)
|
||||||
|
{
|
||||||
|
int low = bcd & 0xf;
|
||||||
|
int high = bcd >> 4;
|
||||||
|
if (low > 9 || high > 9)
|
||||||
|
return -1;
|
||||||
|
return low + 10*high;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dv_extract_timecode(DVDemuxContext* c, uint8_t* frame, char tc[32])
|
||||||
|
{
|
||||||
|
int hh, mm, ss, ff, drop_frame;
|
||||||
|
const uint8_t *tc_pack;
|
||||||
|
|
||||||
|
tc_pack = dv_extract_pack(frame, dv_timecode);
|
||||||
|
if (!tc_pack)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ff = bcd2int(tc_pack[1] & 0x3f);
|
||||||
|
ss = bcd2int(tc_pack[2] & 0x7f);
|
||||||
|
mm = bcd2int(tc_pack[3] & 0x7f);
|
||||||
|
hh = bcd2int(tc_pack[4] & 0x3f);
|
||||||
|
drop_frame = tc_pack[1] >> 6 & 0x1;
|
||||||
|
|
||||||
|
if (ff < 0 || ss < 0 || mm < 0 || hh < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// For PAL systems, drop frame bit is replaced by an arbitrary
|
||||||
|
// bit so its value should not be considered. Drop frame timecode
|
||||||
|
// is only relevant for NTSC systems.
|
||||||
|
if(c->sys->ltc_divisor == 25 || c->sys->ltc_divisor == 50) {
|
||||||
|
drop_frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tc, 32, "%02d:%02d:%02d%c%02d",
|
||||||
|
hh, mm, ss, drop_frame ? ';' : ':', ff);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following 3 functions constitute our interface to the world
|
* The following 3 functions constitute our interface to the world
|
||||||
*/
|
*/
|
||||||
@ -404,6 +446,38 @@ typedef struct RawDVContext {
|
|||||||
uint8_t buf[DV_MAX_FRAME_SIZE];
|
uint8_t buf[DV_MAX_FRAME_SIZE];
|
||||||
} RawDVContext;
|
} RawDVContext;
|
||||||
|
|
||||||
|
static int dv_read_timecode(AVFormatContext *s) {
|
||||||
|
int ret;
|
||||||
|
char timecode[32];
|
||||||
|
int64_t pos = avio_tell(s->pb);
|
||||||
|
|
||||||
|
// Read 3 DIF blocks: Header block and 2 Subcode blocks.
|
||||||
|
int partial_frame_size = 3 * 80;
|
||||||
|
uint8_t *partial_frame = av_mallocz(sizeof(*partial_frame) *
|
||||||
|
partial_frame_size);
|
||||||
|
|
||||||
|
RawDVContext *c = s->priv_data;
|
||||||
|
ret = avio_read(s->pb, partial_frame, partial_frame_size);
|
||||||
|
if (ret < 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
if (ret < partial_frame_size) {
|
||||||
|
ret = -1;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dv_extract_timecode(c->dv_demux, partial_frame, timecode);
|
||||||
|
if (ret)
|
||||||
|
av_dict_set(&s->metadata, "timecode", timecode, 0);
|
||||||
|
else if (ret < 0)
|
||||||
|
av_log(s, AV_LOG_ERROR, "Detected timecode is invalid");
|
||||||
|
|
||||||
|
finish:
|
||||||
|
av_free(partial_frame);
|
||||||
|
avio_seek(s->pb, pos, SEEK_SET);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int dv_read_header(AVFormatContext *s,
|
static int dv_read_header(AVFormatContext *s,
|
||||||
AVFormatParameters *ap)
|
AVFormatParameters *ap)
|
||||||
{
|
{
|
||||||
@ -444,6 +518,9 @@ static int dv_read_header(AVFormatContext *s,
|
|||||||
s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, (AVRational){8,1},
|
s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, (AVRational){8,1},
|
||||||
c->dv_demux->sys->time_base);
|
c->dv_demux->sys->time_base);
|
||||||
|
|
||||||
|
if (s->pb->seekable)
|
||||||
|
dv_read_timecode(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user