|
|
@ -34,6 +34,7 @@ |
|
|
|
#include "libavcodec/dvdata.h" |
|
|
|
#include "libavcodec/dvdata.h" |
|
|
|
#include "libavutil/intreadwrite.h" |
|
|
|
#include "libavutil/intreadwrite.h" |
|
|
|
#include "libavutil/mathematics.h" |
|
|
|
#include "libavutil/mathematics.h" |
|
|
|
|
|
|
|
#include "libavutil/timecode.h" |
|
|
|
#include "dv.h" |
|
|
|
#include "dv.h" |
|
|
|
#include "libavutil/avassert.h" |
|
|
|
#include "libavutil/avassert.h" |
|
|
|
|
|
|
|
|
|
|
@ -275,42 +276,19 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame) |
|
|
|
return size; |
|
|
|
return size; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int bcd2int(uint8_t bcd) |
|
|
|
static int dv_extract_timecode(DVDemuxContext* c, uint8_t* frame, char *tc) |
|
|
|
{ |
|
|
|
{ |
|
|
|
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; |
|
|
|
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
|
|
|
|
// For PAL systems, drop frame bit is replaced by an arbitrary
|
|
|
|
// bit so its value should not be considered. Drop frame timecode
|
|
|
|
// bit so its value should not be considered. Drop frame timecode
|
|
|
|
// is only relevant for NTSC systems.
|
|
|
|
// is only relevant for NTSC systems.
|
|
|
|
if(c->sys->ltc_divisor == 25 || c->sys->ltc_divisor == 50) { |
|
|
|
int prevent_df = c->sys->ltc_divisor == 25 || c->sys->ltc_divisor == 50; |
|
|
|
drop_frame = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
snprintf(tc, 32, "%02d:%02d:%02d%c%02d", |
|
|
|
tc_pack = dv_extract_pack(frame, dv_timecode); |
|
|
|
hh, mm, ss, drop_frame ? ';' : ':', ff); |
|
|
|
if (!tc_pack) |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
av_timecode_make_smpte_tc_string(tc, AV_RB32(tc_pack + 1), prevent_df); |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -454,7 +432,7 @@ typedef struct RawDVContext { |
|
|
|
|
|
|
|
|
|
|
|
static int dv_read_timecode(AVFormatContext *s) { |
|
|
|
static int dv_read_timecode(AVFormatContext *s) { |
|
|
|
int ret; |
|
|
|
int ret; |
|
|
|
char timecode[32]; |
|
|
|
char timecode[AV_TIMECODE_STR_SIZE]; |
|
|
|
int64_t pos = avio_tell(s->pb); |
|
|
|
int64_t pos = avio_tell(s->pb); |
|
|
|
|
|
|
|
|
|
|
|
// Read 3 DIF blocks: Header block and 2 Subcode blocks.
|
|
|
|
// Read 3 DIF blocks: Header block and 2 Subcode blocks.
|
|
|
|