Commit 3c8f30a7 authored by Roman Shaposhnik's avatar Roman Shaposhnik

* Restructuring the division of labor between DV codec and DV format

    [ Based on a patch by Brian Brice (bbrice at newtek dot com) ]

Originally committed as revision 6161 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 712ae911
......@@ -1069,6 +1069,130 @@ static int dvvideo_decode_frame(AVCodecContext *avctx,
return s->sys->frame_size;
}
static inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, uint8_t* buf)
{
/*
* Here's what SMPTE314M says about these two:
* (page 6) APTn, AP1n, AP2n, AP3n: These data shall be identical
* as track application IDs (APTn = 001, AP1n =
* 001, AP2n = 001, AP3n = 001), if the source signal
* comes from a digital VCR. If the signal source is
* unknown, all bits for these data shall be set to 1.
* (page 12) STYPE: STYPE defines a signal type of video signal
* 00000b = 4:1:1 compression
* 00100b = 4:2:2 compression
* XXXXXX = Reserved
* Now, I've got two problems with these statements:
* 1. it looks like APT == 111b should be a safe bet, but it isn't.
* It seems that for PAL as defined in IEC 61834 we have to set
* APT to 000 and for SMPTE314M to 001.
* 2. It is not at all clear what STYPE is used for 4:2:0 PAL
* compression scheme (if any).
*/
int apt = (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0 : 1);
int stype = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 4 : 0);
uint8_t aspect = 0;
if((int)(av_q2d(c->avctx->sample_aspect_ratio) * c->avctx->width / c->avctx->height * 10) == 17) /* 16:9 */
aspect = 0x02;
buf[0] = (uint8_t)pack_id;
switch (pack_id) {
case dv_header525: /* I can't imagine why these two weren't defined as real */
case dv_header625: /* packs in SMPTE314M -- they definitely look like ones */
buf[1] = 0xf8 | /* reserved -- always 1 */
(apt & 0x07); /* APT: Track application ID */
buf[2] = (0 << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */
(0x0f << 3) | /* reserved -- always 1 */
(apt & 0x07); /* AP1: Audio application ID */
buf[3] = (0 << 7) | /* TF2: video data is 0 - valid; 1 - invalid */
(0x0f << 3) | /* reserved -- always 1 */
(apt & 0x07); /* AP2: Video application ID */
buf[4] = (0 << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */
(0x0f << 3) | /* reserved -- always 1 */
(apt & 0x07); /* AP3: Subcode application ID */
break;
case dv_video_source:
buf[1] = 0xff; /* reserved -- always 1 */
buf[2] = (1 << 7) | /* B/W: 0 - b/w, 1 - color */
(1 << 6) | /* following CLF is valid - 0, invalid - 1 */
(3 << 4) | /* CLF: color frames id (see ITU-R BT.470-4) */
0xf; /* reserved -- always 1 */
buf[3] = (3 << 6) | /* reserved -- always 1 */
(c->sys->dsf << 5) | /* system: 60fields/50fields */
stype; /* signal type video compression */
buf[4] = 0xff; /* VISC: 0xff -- no information */
break;
case dv_video_control:
buf[1] = (0 << 6) | /* Copy generation management (CGMS) 0 -- free */
0x3f; /* reserved -- always 1 */
buf[2] = 0xc8 | /* reserved -- always b11001xxx */
aspect;
buf[3] = (1 << 7) | /* Frame/field flag 1 -- frame, 0 -- field */
(1 << 6) | /* First/second field flag 0 -- field 2, 1 -- field 1 */
(1 << 5) | /* Frame change flag 0 -- same picture as before, 1 -- different */
(1 << 4) | /* 1 - interlaced, 0 - noninterlaced */
0xc; /* reserved -- always b1100 */
buf[4] = 0xff; /* reserved -- always 1 */
break;
default:
buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
}
return 5;
}
static void dv_format_frame(DVVideoContext* c, uint8_t* buf)
{
int chan, i, j, k;
for (chan = 0; chan < c->sys->n_difchan; chan++) {
for (i = 0; i < c->sys->difseg_size; i++) {
memset(buf, 0xff, 80 * 6); /* First 6 DIF blocks are for control data */
/* DV header: 1DIF */
buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf);
buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf);
buf += 72; /* unused bytes */
/* DV subcode: 2DIFs */
for (j = 0; j < 2; j++) {
buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf);
for (k = 0; k < 6; k++)
buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf) + 5;
buf += 29; /* unused bytes */
}
/* DV VAUX: 3DIFS */
for (j = 0; j < 3; j++) {
buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf);
buf += dv_write_pack(dv_video_source, c, buf);
buf += dv_write_pack(dv_video_control, c, buf);
buf += 7*5;
buf += dv_write_pack(dv_video_source, c, buf);
buf += dv_write_pack(dv_video_control, c, buf);
buf += 4*5 + 2; /* unused bytes */
}
/* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */
for (j = 0; j < 135; j++) {
if (j%15 == 0) {
memset(buf, 0xff, 80);
buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf);
buf += 77; /* audio control & shuffled PCM audio */
}
buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf);
buf += 77; /* 1 video macro block: 1 bytes control
4 * 14 bytes Y 8x8 data
10 bytes Cr 8x8 data
10 bytes Cb 8x8 data */
}
}
}
}
static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size,
void *data)
{
......@@ -1091,18 +1215,7 @@ static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size,
emms_c();
/* Fill in just enough of the header for dv_frame_profile() to
return the correct result, so that the frame can be decoded
correctly. The rest of the metadata is filled in by the dvvideo
avformat. (this should probably change so that encode_frame()
fills in ALL of the metadata - e.g. for Quicktime-wrapped DV
streams) */
/* NTSC/PAL format */
buf[3] = s->sys->dsf ? 0x80 : 0x00;
/* 25Mbps or 50Mbps */
buf[80*5 + 48 + 3] = (s->sys->pix_fmt == PIX_FMT_YUV422P) ? 0x4 : 0x0;
dv_format_frame(s, buf);
return s->sys->frame_size;
}
......
......@@ -2624,6 +2624,29 @@ static const DVprofile dv_profiles[] = {
}
};
enum dv_section_type {
dv_sect_header = 0x1f,
dv_sect_subcode = 0x3f,
dv_sect_vaux = 0x56,
dv_sect_audio = 0x76,
dv_sect_video = 0x96,
};
enum dv_pack_type {
dv_header525 = 0x3f, /* see dv_write_pack for important details on */
dv_header625 = 0xbf, /* these two packs */
dv_timecode = 0x13,
dv_audio_source = 0x50,
dv_audio_control = 0x51,
dv_audio_recdate = 0x52,
dv_audio_rectime = 0x53,
dv_video_source = 0x60,
dv_video_control = 0x61,
dv_video_recdate = 0x62,
dv_video_rectime = 0x63,
dv_unknown_pack = 0xff,
};
/* minimum number of bytes to read from a DV stream in order to determine the profile */
#define DV_PROFILE_BYTES (6*80) /* 6 DIF blocks */
......@@ -2663,3 +2686,37 @@ static inline const DVprofile* dv_codec_profile(AVCodecContext* codec)
return NULL;
}
static inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num, uint8_t seq_num,
uint8_t dif_num, uint8_t* buf)
{
buf[0] = (uint8_t)t; /* Section type */
buf[1] = (seq_num<<4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */
(chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */
7; /* reserved -- always 1 */
buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */
return 3;
}
static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf)
{
if (syb_num == 0 || syb_num == 6) {
buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */
(0<<4) | /* AP3 (Subcode application ID) */
0x0f; /* reserved -- always 1 */
}
else if (syb_num == 11) {
buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */
0x7f; /* reserved -- always 1 */
}
else {
buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */
(0<<4) | /* APT (Track application ID) */
0x0f; /* reserved -- always 1 */
}
buf[1] = 0xf0 | /* reserved -- always 1 */
(syb_num & 0x0f); /* SSYB number 0 - 11 */
buf[2] = 0xff; /* reserved -- always 1 */
return 3;
}
......@@ -434,6 +434,16 @@ int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr);
void fifo_write(FifoBuffer *f, const uint8_t *buf, int size, uint8_t **wptr_ptr);
int put_fifo(ByteIOContext *pb, FifoBuffer *f, int buf_size, uint8_t **rptr_ptr);
void fifo_realloc(FifoBuffer *f, unsigned int size);
static inline uint8_t fifo_peek(FifoBuffer *f, int offs)
{
return f->buffer[(f->rptr - f->buffer + offs) % (f->end - f->buffer)];
}
static inline void fifo_drain(FifoBuffer *f, int size)
{
f->rptr += size;
if (f->rptr >= f->end)
f->rptr = f->buffer + (f->rptr - f->end);
}
/* media file input */
AVInputFormat *av_find_input_format(const char *short_name);
......
This diff is collapsed.
......@@ -141,11 +141,11 @@ f998347483cef957af497aa0055dca0c *./data/a-snow53.avi
3534748 ./data/a-snow53.avi
799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
stddev: 0.00 PSNR:99.99 bytes:7602176
85529d9838c5a8aef041445fa8ef3c85 *./data/a-dv.dv
2fcbcdc63816e1321bf4b6b5380338d2 *./data/a-dv.dv
7200000 ./data/a-dv.dv
c2082cd8adf417c4ebc32654e446cba1 *./data/out.yuv
stddev: 8.86 PSNR:29.17 bytes:7602176
ff5eb084624f9a2846840a215b95a112 *./data/a-dv.dv
4f71942eb699bf3b12508a9e777a319f *./data/a-dv.dv
14400000 ./data/a-dv.dv
fc866b8879a34f5b440647e5135e4bfb *./data/out.yuv
stddev: 8.45 PSNR:29.58 bytes:7602176
......
......@@ -28,7 +28,7 @@ ffmpeg regression test
8bf16d40a2ec19fa36b124a928e47e23 *./data/b-libav.nut
332358 ./data/b-libav.nut
./data/b-libav.nut CRC=0x1fdd352c
2cc647904d3cca01703f36056b9d3f42 *./data/b-libav.dv
26c41db318d9aacfd6b9e734c0ea4d94 *./data/b-libav.dv
3600000 ./data/b-libav.dv
./data/b-libav.dv CRC=0xa6b8b635
304ee17506e4526ba04285f6cd14630f *./data/b-libav.gxf
......
......@@ -141,11 +141,11 @@ stddev: 10.93 PSNR:27.34 bytes:7602176
2726606 ./data/a-snow53.avi
dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
stddev: 0.00 PSNR:99.99 bytes:7602176
6568326ee439099e8a0e1680336ed351 *./data/a-dv.dv
af9f474238c9c68cb32e389659ee25ab *./data/a-dv.dv
7200000 ./data/a-dv.dv
bb69dda7a84a5b166434e28e1243d3d1 *./data/out.yuv
stddev: 2.99 PSNR:38.59 bytes:7602176
177cbbbe50cbb67ae3bd6e7f10ff968b *./data/a-dv.dv
91dc1c1dc4a8cca72f27d85db6d7636f *./data/a-dv.dv
14400000 ./data/a-dv.dv
74b01209bb5e096d570dd4df112bb82d *./data/out.yuv
stddev: 2.98 PSNR:38.61 bytes:7602176
......
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