|
|
|
@ -77,100 +77,100 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu |
|
|
|
|
buf[0] = (uint8_t)pack_id; |
|
|
|
|
switch (pack_id) { |
|
|
|
|
case dv_timecode: |
|
|
|
|
ct = (time_t)(c->frames / ((float)c->sys->frame_rate / |
|
|
|
|
(float)c->sys->frame_rate_base)); |
|
|
|
|
brktimegm(ct, &tc); |
|
|
|
|
/*
|
|
|
|
|
* LTC drop-frame frame counter drops two frames (0 and 1) every |
|
|
|
|
* minute, unless it is exactly divisible by 10 |
|
|
|
|
*/ |
|
|
|
|
ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor; |
|
|
|
|
buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */ |
|
|
|
|
(1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */ |
|
|
|
|
((ltc_frame / 10) << 4) | /* Tens of frames */ |
|
|
|
|
(ltc_frame % 10); /* Units of frames */ |
|
|
|
|
buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */ |
|
|
|
|
((tc.tm_sec / 10) << 4) | /* Tens of seconds */ |
|
|
|
|
(tc.tm_sec % 10); /* Units of seconds */ |
|
|
|
|
buf[3] = (1 << 7) | /* Binary group flag BGF0 */ |
|
|
|
|
((tc.tm_min / 10) << 4) | /* Tens of minutes */ |
|
|
|
|
(tc.tm_min % 10); /* Units of minutes */ |
|
|
|
|
buf[4] = (1 << 7) | /* Binary group flag BGF2 */ |
|
|
|
|
(1 << 6) | /* Binary group flag BGF1 */ |
|
|
|
|
((tc.tm_hour / 10) << 4) | /* Tens of hours */ |
|
|
|
|
(tc.tm_hour % 10); /* Units of hours */ |
|
|
|
|
break; |
|
|
|
|
ct = (time_t)(c->frames / ((float)c->sys->frame_rate / |
|
|
|
|
(float)c->sys->frame_rate_base)); |
|
|
|
|
brktimegm(ct, &tc); |
|
|
|
|
/*
|
|
|
|
|
* LTC drop-frame frame counter drops two frames (0 and 1) every |
|
|
|
|
* minute, unless it is exactly divisible by 10 |
|
|
|
|
*/ |
|
|
|
|
ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor; |
|
|
|
|
buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */ |
|
|
|
|
(1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */ |
|
|
|
|
((ltc_frame / 10) << 4) | /* Tens of frames */ |
|
|
|
|
(ltc_frame % 10); /* Units of frames */ |
|
|
|
|
buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */ |
|
|
|
|
((tc.tm_sec / 10) << 4) | /* Tens of seconds */ |
|
|
|
|
(tc.tm_sec % 10); /* Units of seconds */ |
|
|
|
|
buf[3] = (1 << 7) | /* Binary group flag BGF0 */ |
|
|
|
|
((tc.tm_min / 10) << 4) | /* Tens of minutes */ |
|
|
|
|
(tc.tm_min % 10); /* Units of minutes */ |
|
|
|
|
buf[4] = (1 << 7) | /* Binary group flag BGF2 */ |
|
|
|
|
(1 << 6) | /* Binary group flag BGF1 */ |
|
|
|
|
((tc.tm_hour / 10) << 4) | /* Tens of hours */ |
|
|
|
|
(tc.tm_hour % 10); /* Units of hours */ |
|
|
|
|
break; |
|
|
|
|
case dv_audio_source: /* AAUX source pack */ |
|
|
|
|
va_start(ap, buf); |
|
|
|
|
buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */ |
|
|
|
|
(1 << 6) | /* reserved -- always 1 */ |
|
|
|
|
(dv_audio_frame_size(c->sys, c->frames) - |
|
|
|
|
c->sys->audio_min_samples[0]); |
|
|
|
|
/* # of samples */ |
|
|
|
|
buf[2] = (0 << 7) | /* multi-stereo */ |
|
|
|
|
(0 << 5) | /* #of audio channels per block: 0 -- 1 channel */ |
|
|
|
|
(0 << 4) | /* pair bit: 0 -- one pair of channels */ |
|
|
|
|
!!va_arg(ap, int); /* audio mode */ |
|
|
|
|
buf[3] = (1 << 7) | /* res */ |
|
|
|
|
(1 << 6) | /* multi-language flag */ |
|
|
|
|
(c->sys->dsf << 5) | /* system: 60fields/50fields */ |
|
|
|
|
(c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */ |
|
|
|
|
buf[4] = (1 << 7) | /* emphasis: 1 -- off */ |
|
|
|
|
(0 << 6) | /* emphasis time constant: 0 -- reserved */ |
|
|
|
|
(0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */ |
|
|
|
|
0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */ |
|
|
|
|
va_end(ap); |
|
|
|
|
break; |
|
|
|
|
va_start(ap, buf); |
|
|
|
|
buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */ |
|
|
|
|
(1 << 6) | /* reserved -- always 1 */ |
|
|
|
|
(dv_audio_frame_size(c->sys, c->frames) - |
|
|
|
|
c->sys->audio_min_samples[0]); |
|
|
|
|
/* # of samples */ |
|
|
|
|
buf[2] = (0 << 7) | /* multi-stereo */ |
|
|
|
|
(0 << 5) | /* #of audio channels per block: 0 -- 1 channel */ |
|
|
|
|
(0 << 4) | /* pair bit: 0 -- one pair of channels */ |
|
|
|
|
!!va_arg(ap, int); /* audio mode */ |
|
|
|
|
buf[3] = (1 << 7) | /* res */ |
|
|
|
|
(1 << 6) | /* multi-language flag */ |
|
|
|
|
(c->sys->dsf << 5) | /* system: 60fields/50fields */ |
|
|
|
|
(c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */ |
|
|
|
|
buf[4] = (1 << 7) | /* emphasis: 1 -- off */ |
|
|
|
|
(0 << 6) | /* emphasis time constant: 0 -- reserved */ |
|
|
|
|
(0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */ |
|
|
|
|
0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */ |
|
|
|
|
va_end(ap); |
|
|
|
|
break; |
|
|
|
|
case dv_audio_control: |
|
|
|
|
buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */ |
|
|
|
|
(1 << 4) | /* input source: 1 -- digital input */ |
|
|
|
|
(3 << 2) | /* compression: 3 -- no information */ |
|
|
|
|
0; /* misc. info/SMPTE emphasis off */ |
|
|
|
|
buf[2] = (1 << 7) | /* recording start point: 1 -- no */ |
|
|
|
|
(1 << 6) | /* recording end point: 1 -- no */ |
|
|
|
|
(1 << 3) | /* recording mode: 1 -- original */ |
|
|
|
|
7; |
|
|
|
|
buf[3] = (1 << 7) | /* direction: 1 -- forward */ |
|
|
|
|
(c->sys->pix_fmt == PIX_FMT_YUV420P ? 0x20 : /* speed */ |
|
|
|
|
c->sys->ltc_divisor*4); |
|
|
|
|
buf[4] = (1 << 7) | /* reserved -- always 1 */ |
|
|
|
|
0x7f; /* genre category */ |
|
|
|
|
break; |
|
|
|
|
buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */ |
|
|
|
|
(1 << 4) | /* input source: 1 -- digital input */ |
|
|
|
|
(3 << 2) | /* compression: 3 -- no information */ |
|
|
|
|
0; /* misc. info/SMPTE emphasis off */ |
|
|
|
|
buf[2] = (1 << 7) | /* recording start point: 1 -- no */ |
|
|
|
|
(1 << 6) | /* recording end point: 1 -- no */ |
|
|
|
|
(1 << 3) | /* recording mode: 1 -- original */ |
|
|
|
|
7; |
|
|
|
|
buf[3] = (1 << 7) | /* direction: 1 -- forward */ |
|
|
|
|
(c->sys->pix_fmt == PIX_FMT_YUV420P ? 0x20 : /* speed */ |
|
|
|
|
c->sys->ltc_divisor*4); |
|
|
|
|
buf[4] = (1 << 7) | /* reserved -- always 1 */ |
|
|
|
|
0x7f; /* genre category */ |
|
|
|
|
break; |
|
|
|
|
case dv_audio_recdate: |
|
|
|
|
case dv_video_recdate: /* VAUX recording date */ |
|
|
|
|
ct = c->start_time + (time_t)(c->frames / |
|
|
|
|
((float)c->sys->frame_rate / (float)c->sys->frame_rate_base)); |
|
|
|
|
brktimegm(ct, &tc); |
|
|
|
|
buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */ |
|
|
|
|
/* 0xff is very likely to be "unknown" */ |
|
|
|
|
buf[2] = (3 << 6) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_mday / 10) << 4) | /* Tens of day */ |
|
|
|
|
(tc.tm_mday % 10); /* Units of day */ |
|
|
|
|
buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */ |
|
|
|
|
((tc.tm_mon / 10) << 4) | /* Tens of month */ |
|
|
|
|
(tc.tm_mon % 10); /* Units of month */ |
|
|
|
|
buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */ |
|
|
|
|
(tc.tm_year % 10); /* Units of year */ |
|
|
|
|
break; |
|
|
|
|
ct = c->start_time + (time_t)(c->frames / |
|
|
|
|
((float)c->sys->frame_rate / (float)c->sys->frame_rate_base)); |
|
|
|
|
brktimegm(ct, &tc); |
|
|
|
|
buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */ |
|
|
|
|
/* 0xff is very likely to be "unknown" */ |
|
|
|
|
buf[2] = (3 << 6) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_mday / 10) << 4) | /* Tens of day */ |
|
|
|
|
(tc.tm_mday % 10); /* Units of day */ |
|
|
|
|
buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */ |
|
|
|
|
((tc.tm_mon / 10) << 4) | /* Tens of month */ |
|
|
|
|
(tc.tm_mon % 10); /* Units of month */ |
|
|
|
|
buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */ |
|
|
|
|
(tc.tm_year % 10); /* Units of year */ |
|
|
|
|
break; |
|
|
|
|
case dv_audio_rectime: /* AAUX recording time */ |
|
|
|
|
case dv_video_rectime: /* VAUX recording time */ |
|
|
|
|
ct = c->start_time + (time_t)(c->frames / |
|
|
|
|
((float)c->sys->frame_rate / (float)c->sys->frame_rate_base)); |
|
|
|
|
brktimegm(ct, &tc); |
|
|
|
|
buf[1] = (3 << 6) | /* reserved -- always 1 */ |
|
|
|
|
0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */ |
|
|
|
|
buf[2] = (1 << 7) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_sec / 10) << 4) | /* Tens of seconds */ |
|
|
|
|
(tc.tm_sec % 10); /* Units of seconds */ |
|
|
|
|
buf[3] = (1 << 7) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_min / 10) << 4) | /* Tens of minutes */ |
|
|
|
|
(tc.tm_min % 10); /* Units of minutes */ |
|
|
|
|
buf[4] = (3 << 6) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_hour / 10) << 4) | /* Tens of hours */ |
|
|
|
|
(tc.tm_hour % 10); /* Units of hours */ |
|
|
|
|
break; |
|
|
|
|
ct = c->start_time + (time_t)(c->frames / |
|
|
|
|
((float)c->sys->frame_rate / (float)c->sys->frame_rate_base)); |
|
|
|
|
brktimegm(ct, &tc); |
|
|
|
|
buf[1] = (3 << 6) | /* reserved -- always 1 */ |
|
|
|
|
0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */ |
|
|
|
|
buf[2] = (1 << 7) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_sec / 10) << 4) | /* Tens of seconds */ |
|
|
|
|
(tc.tm_sec % 10); /* Units of seconds */ |
|
|
|
|
buf[3] = (1 << 7) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_min / 10) << 4) | /* Tens of minutes */ |
|
|
|
|
(tc.tm_min % 10); /* Units of minutes */ |
|
|
|
|
buf[4] = (3 << 6) | /* reserved -- always 1 */ |
|
|
|
|
((tc.tm_hour / 10) << 4) | /* Tens of hours */ |
|
|
|
|
(tc.tm_hour % 10); /* Units of hours */ |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
buf[1] = buf[2] = buf[3] = buf[4] = 0xff; |
|
|
|
|
buf[1] = buf[2] = buf[3] = buf[4] = 0xff; |
|
|
|
|
} |
|
|
|
|
return 5; |
|
|
|
|
} |
|
|
|
@ -181,19 +181,19 @@ static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr) |
|
|
|
|
size = 4 * dv_audio_frame_size(c->sys, c->frames); |
|
|
|
|
frame_ptr += channel * c->sys->difseg_size * 150 * 80; |
|
|
|
|
for (i = 0; i < c->sys->difseg_size; i++) { |
|
|
|
|
frame_ptr += 6 * 80; /* skip DIF segment header */ |
|
|
|
|
for (j = 0; j < 9; j++) { |
|
|
|
|
dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], i >= c->sys->difseg_size/2); |
|
|
|
|
for (d = 8; d < 80; d+=2) { |
|
|
|
|
of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride; |
|
|
|
|
if (of*2 >= size) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
frame_ptr[d] = av_fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit
|
|
|
|
|
frame_ptr[d+1] = av_fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM
|
|
|
|
|
} |
|
|
|
|
frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ |
|
|
|
|
} |
|
|
|
|
frame_ptr += 6 * 80; /* skip DIF segment header */ |
|
|
|
|
for (j = 0; j < 9; j++) { |
|
|
|
|
dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], i >= c->sys->difseg_size/2); |
|
|
|
|
for (d = 8; d < 80; d+=2) { |
|
|
|
|
of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride; |
|
|
|
|
if (of*2 >= size) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
frame_ptr[d] = av_fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit
|
|
|
|
|
frame_ptr[d+1] = av_fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM
|
|
|
|
|
} |
|
|
|
|
frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -240,27 +240,27 @@ int dv_assemble_frame(DVMuxContext *c, AVStream* st, |
|
|
|
|
|
|
|
|
|
switch (st->codec->codec_type) { |
|
|
|
|
case CODEC_TYPE_VIDEO: |
|
|
|
|
/* FIXME: we have to have more sensible approach than this one */ |
|
|
|
|
if (c->has_video) |
|
|
|
|
av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); |
|
|
|
|
/* FIXME: we have to have more sensible approach than this one */ |
|
|
|
|
if (c->has_video) |
|
|
|
|
av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); |
|
|
|
|
|
|
|
|
|
memcpy(*frame, data, c->sys->frame_size); |
|
|
|
|
c->has_video = 1; |
|
|
|
|
break; |
|
|
|
|
memcpy(*frame, data, c->sys->frame_size); |
|
|
|
|
c->has_video = 1; |
|
|
|
|
break; |
|
|
|
|
case CODEC_TYPE_AUDIO: |
|
|
|
|
for (i = 0; i < c->n_ast && st != c->ast[i]; i++); |
|
|
|
|
for (i = 0; i < c->n_ast && st != c->ast[i]; i++); |
|
|
|
|
|
|
|
|
|
/* FIXME: we have to have more sensible approach than this one */ |
|
|
|
|
if (av_fifo_size(&c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) |
|
|
|
|
av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); |
|
|
|
|
av_fifo_write(&c->audio_data[i], data, data_size); |
|
|
|
|
if (av_fifo_size(&c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) |
|
|
|
|
av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); |
|
|
|
|
av_fifo_write(&c->audio_data[i], data, data_size); |
|
|
|
|
|
|
|
|
|
/* Lets see if we've got enough audio for one DV frame */ |
|
|
|
|
c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i); |
|
|
|
|
/* Lets see if we've got enough audio for one DV frame */ |
|
|
|
|
c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Lets see if we have enough data to construct one DV frame */ |
|
|
|
@ -268,9 +268,9 @@ int dv_assemble_frame(DVMuxContext *c, AVStream* st, |
|
|
|
|
dv_inject_metadata(c, *frame); |
|
|
|
|
c->has_audio = 0; |
|
|
|
|
for (i=0; i<c->n_ast; i++) { |
|
|
|
|
dv_inject_audio(c, i, *frame); |
|
|
|
|
av_fifo_drain(&c->audio_data[i], reqasize); |
|
|
|
|
c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i); |
|
|
|
|
dv_inject_audio(c, i, *frame); |
|
|
|
|
av_fifo_drain(&c->audio_data[i], reqasize); |
|
|
|
|
c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c->has_video = 0; |
|
|
|
@ -298,18 +298,18 @@ DVMuxContext* dv_init_mux(AVFormatContext* s) |
|
|
|
|
|
|
|
|
|
/* We have to sort out where audio and where video stream is */ |
|
|
|
|
for (i=0; i<s->nb_streams; i++) { |
|
|
|
|
switch (s->streams[i]->codec->codec_type) { |
|
|
|
|
case CODEC_TYPE_VIDEO: |
|
|
|
|
if (vst) return NULL; |
|
|
|
|
vst = s->streams[i]; |
|
|
|
|
break; |
|
|
|
|
case CODEC_TYPE_AUDIO: |
|
|
|
|
if (c->n_ast > 1) return NULL; |
|
|
|
|
c->ast[c->n_ast++] = s->streams[i]; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
goto bail_out; |
|
|
|
|
} |
|
|
|
|
switch (s->streams[i]->codec->codec_type) { |
|
|
|
|
case CODEC_TYPE_VIDEO: |
|
|
|
|
if (vst) return NULL; |
|
|
|
|
vst = s->streams[i]; |
|
|
|
|
break; |
|
|
|
|
case CODEC_TYPE_AUDIO: |
|
|
|
|
if (c->n_ast > 1) return NULL; |
|
|
|
|
c->ast[c->n_ast++] = s->streams[i]; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
goto bail_out; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Some checks -- DV format is very picky about its incoming streams */ |
|
|
|
|