summaryrefslogtreecommitdiff
path: root/libavcodec/dv.c
diff options
context:
space:
mode:
authorRoman Shaposhnik <roman@shaposhnik.org>2006-09-04 03:33:11 +0000
committerRoman Shaposhnik <roman@shaposhnik.org>2006-09-04 03:33:11 +0000
commit3c8f30a745ea71f2fd372e58a3f7d227c1f5d5c6 (patch)
tree2e19d5748024ba7fb0331be34f63051d343f0e78 /libavcodec/dv.c
parent712ae911bbc2140860ec6d3f35317a81ecc51e2a (diff)
* 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
Diffstat (limited to 'libavcodec/dv.c')
-rw-r--r--libavcodec/dv.c137
1 files changed, 125 insertions, 12 deletions
diff --git a/libavcodec/dv.c b/libavcodec/dv.c
index 90d101813b..fa2952dc65 100644
--- a/libavcodec/dv.c
+++ b/libavcodec/dv.c
@@ -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;
}