changeset 1489:337d13aee605 libavcodec

* DV handling was streamlined for both muxing/demuxing and decoding. All muxing/demuxing functionality is now available in libavformat/dv.[ch]. * dv1394.c and avidec.c were hooked up with general DV demuxer. * DVAUDIO is dead! Long live pcm_s16le! * DV audio is now always recognized -- which means we can now hear all those ducks quaking in pond.dv.
author romansh
date Mon, 29 Sep 2003 17:54:07 +0000
parents 766a2f4edbea
children 0355f2b3519a
files allcodecs.c avcodec.h dv.c dvdata.h
diffstat 4 files changed, 152 insertions(+), 295 deletions(-) [+]
line wrap: on
line diff
--- a/allcodecs.c	Mon Sep 29 15:44:59 2003 +0000
+++ b/allcodecs.c	Mon Sep 29 17:54:07 2003 +0000
@@ -103,7 +103,6 @@
     register_avcodec(&mpeg_xvmc_decoder);
 #endif
     register_avcodec(&dvvideo_decoder);
-    register_avcodec(&dvaudio_decoder);
     register_avcodec(&mjpeg_decoder);
     register_avcodec(&mjpegb_decoder);
     register_avcodec(&mp2_decoder);
--- a/avcodec.h	Mon Sep 29 15:44:59 2003 +0000
+++ b/avcodec.h	Mon Sep 29 17:54:07 2003 +0000
@@ -1388,7 +1388,6 @@
 extern AVCodec svq1_decoder;
 extern AVCodec svq3_decoder;
 extern AVCodec dvvideo_decoder;
-extern AVCodec dvaudio_decoder;
 extern AVCodec wmav1_decoder;
 extern AVCodec wmav2_decoder;
 extern AVCodec mjpeg_decoder;
--- a/dv.c	Mon Sep 29 15:44:59 2003 +0000
+++ b/dv.c	Mon Sep 29 17:54:07 2003 +0000
@@ -25,34 +25,29 @@
 #include "dsputil.h"
 #include "mpegvideo.h"
 #include "simple_idct.h"
-
-#define NTSC_FRAME_SIZE 120000
-#define PAL_FRAME_SIZE  144000
-
-#define TEX_VLC_BITS 9
+#include "dvdata.h"
 
 typedef struct DVVideoDecodeContext {
-    AVCodecContext *avctx;
+    const DVprofile* sys;
     GetBitContext gb;
-    VLC *vlc;
-    int sampling_411; /* 0 = 420, 1 = 411 */
-    int width, height;
-    uint8_t *current_picture[3]; /* picture structure */
     AVFrame picture;
-    int linesize[3];
     DCTELEM block[5*6][64] __align8;
+    
+    /* FIXME: the following is extracted from DSP */
     uint8_t dv_zigzag[2][64];
     uint8_t idct_permutation[64];
+    void (*get_pixels)(DCTELEM *block, const uint8_t *pixels, int line_size);
+    void (*fdct)(DCTELEM *block);
+    
     /* XXX: move it to static storage ? */
     uint8_t dv_shift[2][22][64];
     void (*idct_put[2])(uint8_t *dest, int line_size, DCTELEM *block);
 } DVVideoDecodeContext;
 
-#include "dvdata.h"
-
-static VLC dv_vlc;
+#define TEX_VLC_BITS 9
 /* XXX: also include quantization */
 static RL_VLC_ELEM *dv_rl_vlc[1];
+static VLC_TYPE dv_vlc_codes[15][23];
 
 static void dv_build_unquantize_tables(DVVideoDecodeContext *s)
 {
@@ -85,6 +80,7 @@
 
     if (!done) {
         int i;
+        VLC dv_vlc;
 
         done = 1;
 
@@ -114,6 +110,12 @@
             dv_rl_vlc[0][i].level = level;
             dv_rl_vlc[0][i].run = run;
         }
+
+	memset(dv_vlc_codes, 0xff, sizeof(dv_vlc_codes));
+	for (i = 0; i < NB_DV_VLC - 1; i++) {
+	   if (dv_vlc_run[i] < 15 && dv_vlc_level[i] < 23 && dv_vlc_len[i] < 15)
+	       dv_vlc_codes[dv_vlc_run[i]][dv_vlc_level[i]] = i;
+	}
     }
 
     /* ugly way to get the idct & scantable */
@@ -124,6 +126,9 @@
     if (DCT_common_init(&s2) < 0)
        return -1;
 
+    s->get_pixels = s2.dsp.get_pixels;
+    s->fdct = s2.dsp.fdct;
+    
     s->idct_put[0] = s2.dsp.idct_put;
     memcpy(s->idct_permutation, s2.dsp.idct_permutation, 64);
     memcpy(s->dv_zigzag[0], s2.intra_scantable.permutated, 64);
@@ -134,11 +139,11 @@
 
     /* XXX: do it only for constant case */
     dv_build_unquantize_tables(s);
-    
+
     return 0;
 }
 
-//#define VLC_DEBUG
+// #define VLC_DEBUG
 
 typedef struct BlockInfo {
     const uint8_t *shift_table;
@@ -450,29 +455,29 @@
         v = *mb_pos_ptr++;
         mb_x = v & 0xff;
         mb_y = v >> 8;
-        y_ptr = s->current_picture[0] + (mb_y * s->linesize[0] * 8) + (mb_x * 8);
-        if (s->sampling_411)
-            c_offset = (mb_y * s->linesize[1] * 8) + ((mb_x >> 2) * 8);
+        y_ptr = s->picture.data[0] + (mb_y * s->picture.linesize[0] * 8) + (mb_x * 8);
+        if (s->sys->pix_fmt == PIX_FMT_YUV411P)
+            c_offset = (mb_y * s->picture.linesize[1] * 8) + ((mb_x >> 2) * 8);
         else
-            c_offset = ((mb_y >> 1) * s->linesize[1] * 8) + ((mb_x >> 1) * 8);
+            c_offset = ((mb_y >> 1) * s->picture.linesize[1] * 8) + ((mb_x >> 1) * 8);
         for(j = 0;j < 6; j++) {
             idct_put = s->idct_put[mb->dct_mode];
             if (j < 4) {
-                if (s->sampling_411 && mb_x < (704 / 8)) {
+                if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x < (704 / 8)) {
                     /* NOTE: at end of line, the macroblock is handled as 420 */
-                    idct_put(y_ptr + (j * 8), s->linesize[0], block);
+                    idct_put(y_ptr + (j * 8), s->picture.linesize[0], block);
                 } else {
-                    idct_put(y_ptr + ((j & 1) * 8) + ((j >> 1) * 8 * s->linesize[0]),
-                             s->linesize[0], block);
+                    idct_put(y_ptr + ((j & 1) * 8) + ((j >> 1) * 8 * s->picture.linesize[0]),
+                             s->picture.linesize[0], block);
                 }
             } else {
-                if (s->sampling_411 && mb_x >= (704 / 8)) {
+                if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) {
                     uint8_t pixels[64], *c_ptr, *c_ptr1, *ptr;
                     int y, linesize;
                     /* NOTE: at end of line, the macroblock is handled as 420 */
                     idct_put(pixels, 8, block);
-                    linesize = s->linesize[6 - j];
-                    c_ptr = s->current_picture[6 - j] + c_offset;
+                    linesize = s->picture.linesize[6 - j];
+                    c_ptr = s->picture.data[6 - j] + c_offset;
                     ptr = pixels;
                     for(y = 0;y < 8; y++) {
                         /* convert to 411P */
@@ -486,8 +491,8 @@
                     }
                 } else {
                     /* don't ask me why they inverted Cb and Cr ! */
-                    idct_put(s->current_picture[6 - j] + c_offset, 
-                             s->linesize[6 - j], block);
+                    idct_put(s->picture.data[6 - j] + c_offset, 
+                             s->picture.linesize[6 - j], block);
                 }
             }
             block += 64;
@@ -496,7 +501,6 @@
     }
 }
 
-
 /* NOTE: exactly one frame must be given (120000 bytes for NTSC,
    144000 bytes for PAL) */
 static int dvvideo_decode_frame(AVCodecContext *avctx, 
@@ -504,115 +508,35 @@
                                  uint8_t *buf, int buf_size)
 {
     DVVideoDecodeContext *s = avctx->priv_data;
-    int sct, dsf, apt, ds, nb_dif_segs, vs, width, height, i, packet_size;
-    uint8_t *buf_ptr;
+    int ds, vs;
     const uint16_t *mb_pos_ptr;
     
-    /* parse id */
-    init_get_bits(&s->gb, buf, buf_size*8);
-    sct = get_bits(&s->gb, 3);
-    if (sct != 0)
-        return -1;
-    skip_bits(&s->gb, 5);
-    get_bits(&s->gb, 4); /* dsn (sequence number */
-    get_bits(&s->gb, 1); /* fsc (channel number) */
-    skip_bits(&s->gb, 3);
-    get_bits(&s->gb, 8); /* dbn (diff block number 0-134) */
-
-    dsf = get_bits(&s->gb, 1); /* 0 = NTSC 1 = PAL */
-    if (get_bits(&s->gb, 1) != 0)
-        return -1;
-    skip_bits(&s->gb, 11);
-    apt = get_bits(&s->gb, 3); /* apt */
-
-    get_bits(&s->gb, 1); /* tf1 */
-    skip_bits(&s->gb, 4);
-    get_bits(&s->gb, 3); /* ap1 */
-
-    get_bits(&s->gb, 1); /* tf2 */
-    skip_bits(&s->gb, 4);
-    get_bits(&s->gb, 3); /* ap2 */
+    s->sys = dv_frame_profile(buf);
+    if (!s->sys || buf_size < s->sys->frame_size)
+        return -1; /* NOTE: we only accept several full frames */
 
-    get_bits(&s->gb, 1); /* tf3 */
-    skip_bits(&s->gb, 4);
-    get_bits(&s->gb, 3); /* ap3 */
-    
-    /* init size */
-    width = 720;
-    if (dsf) {
-        avctx->frame_rate = 25;
-	avctx->frame_rate_base = 1;
-        packet_size = PAL_FRAME_SIZE;
-        height = 576;
-        nb_dif_segs = 12;
-    } else {
-        avctx->frame_rate = 30000;
-	avctx->frame_rate_base = 1001;
-        packet_size = NTSC_FRAME_SIZE;
-        height = 480;
-        nb_dif_segs = 10;
-    }
-    /* NOTE: we only accept several full frames */
-    if (buf_size < packet_size)
-        return -1;
-    
-    /* NTSC[dsf == 0] is always 720x480, 4:1:1
-     *  PAL[dsf == 1] is always 720x576, 4:2:0 for IEC 68134[apt == 0]
-     *  but for the SMPTE 314M[apt == 1] it is 720x576, 4:1:1
-     */
-    s->sampling_411 = !dsf || apt;
-    if (s->sampling_411) {
-        mb_pos_ptr = dsf ? dv_place_411P : dv_place_411;
-        avctx->pix_fmt = PIX_FMT_YUV411P;
-    } else {
-        mb_pos_ptr = dv_place_420;
-        avctx->pix_fmt = PIX_FMT_YUV420P;
-    }
-
-    avctx->width = width;
-    avctx->height = height;
-    
-    /* Once again, this is pretty complicated by the fact that the same
-     * field is used differently by IEC 68134[apt == 0] and 
-     * SMPTE 314M[apt == 1].
-     */
-    if (buf[VAUX_TC61_OFFSET] == 0x61 &&
-        ((apt == 0 && (buf[VAUX_TC61_OFFSET + 2] & 0x07) == 0x07) ||
-	 (apt == 1 && (buf[VAUX_TC61_OFFSET + 2] & 0x07) == 0x02)))
-        avctx->aspect_ratio = 16.0 / 9.0;
-    else
-        avctx->aspect_ratio = 4.0 / 3.0;
-
+	
     if(s->picture.data[0])
         avctx->release_buffer(avctx, &s->picture);
     
-    s->picture.reference= 0;
+    s->picture.reference = 0;
+    avctx->pix_fmt = s->sys->pix_fmt;
     if(avctx->get_buffer(avctx, &s->picture) < 0) {
         fprintf(stderr, "get_buffer() failed\n");
         return -1;
     }
 
-    for(i=0;i<3;i++) {
-        s->current_picture[i] = s->picture.data[i];
-        s->linesize[i] = s->picture.linesize[i];
-        if (!s->current_picture[i])
-            return -1;
-    }
-    s->width = width;
-    s->height = height;
-
     /* for each DIF segment */
-    buf_ptr = buf;
-    for (ds = 0; ds < nb_dif_segs; ds++) {
-        buf_ptr += 6 * 80; /* skip DIF segment header */
+    mb_pos_ptr = s->sys->video_place;
+    for (ds = 0; ds < s->sys->difseg_size; ds++) {
+        buf += 6 * 80; /* skip DIF segment header */
         
         for(vs = 0; vs < 27; vs++) {
-            if ((vs % 3) == 0) {
-                /* skip audio block */
-                buf_ptr += 80;
-            }
-            dv_decode_video_segment(s, buf_ptr, mb_pos_ptr);
-            buf_ptr += 5 * 80;
+            if ((vs % 3) == 0)
+	        buf += 80; /* skip audio block */
+            
+	    dv_decode_video_segment(s, buf, mb_pos_ptr);
+            buf += 5 * 80;
             mb_pos_ptr += 5;
         }
     }
@@ -623,7 +547,7 @@
     *data_size = sizeof(AVFrame);
     *(AVFrame*)data= s->picture;
     
-    return packet_size;
+    return s->sys->frame_size;
 }
 
 static int dvvideo_decode_end(AVCodecContext *avctx)
@@ -645,158 +569,3 @@
     CODEC_CAP_DR1,
     NULL
 };
-
-typedef struct DVAudioDecodeContext {
-    AVCodecContext *avctx;
-    GetBitContext gb;
-} DVAudioDecodeContext;
-
-static int dvaudio_decode_init(AVCodecContext *avctx)
-{
-    //    DVAudioDecodeContext *s = avctx->priv_data;
-    return 0;
-}
-
-static uint16_t dv_audio_12to16(uint16_t sample)
-{
-    uint16_t shift, result;
-    
-    sample = (sample < 0x800) ? sample : sample | 0xf000;
-    shift = (sample & 0xf00) >> 8;
-
-    if (shift < 0x2 || shift > 0xd) {
-	result = sample;
-    } else if (shift < 0x8) {
-        shift--;
-	result = (sample - (256 * shift)) << shift;
-    } else {
-	shift = 0xe - shift;
-	result = ((sample + ((256 * shift) + 1)) << shift) - 1;
-    }
-
-    return result;
-}
-
-/* NOTE: exactly one frame must be given (120000 bytes for NTSC,
-   144000 bytes for PAL) 
-
-   There's a couple of assumptions being made here:
-         1. By default we silence erroneous (0x8000/16bit 0x800/12bit) 
-	    audio samples. We can pass them upwards when ffmpeg will be ready
-	    to deal with them.
-	 2. We don't do software emphasis.
-	 3. Audio is always returned as 16bit linear samples: 12bit
-	    nonlinear samples are converted into 16bit linear ones.
-*/
-static int dvaudio_decode_frame(AVCodecContext *avctx, 
-                                 void *data, int *data_size,
-                                 uint8_t *buf, int buf_size)
-{
-    DVVideoDecodeContext *s = avctx->priv_data;
-    const uint16_t (*unshuffle)[9];
-    int smpls, freq, quant, sys, stride, difseg, ad, dp, nb_dif_segs, i;
-    uint16_t lc, rc;
-    uint8_t *buf_ptr;
-    
-    /* parse id */
-    init_get_bits(&s->gb, &buf[AAUX_AS_OFFSET], 5*8);
-    i = get_bits(&s->gb, 8);
-    if (i != 0x50) { /* No audio ? */
-	*data_size = 0;
-	return buf_size;
-    }
-    
-    get_bits(&s->gb, 1); /* 0 - locked audio, 1 - unlocked audio */
-    skip_bits(&s->gb, 1);
-    smpls = get_bits(&s->gb, 6); /* samples in this frame - min. samples */
-
-    skip_bits(&s->gb, 8);
-
-    skip_bits(&s->gb, 2);
-    sys = get_bits(&s->gb, 1); /* 0 - 60 fields, 1 = 50 fields */
-    skip_bits(&s->gb, 5);
-
-    get_bits(&s->gb, 1); /* 0 - emphasis on, 1 - emphasis off */
-    get_bits(&s->gb, 1); /* 0 - reserved, 1 - emphasis time constant 50/15us */
-    freq = get_bits(&s->gb, 3); /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
-    quant = get_bits(&s->gb, 3); /* 0 - 16bit linear, 1 - 12bit nonlinear */
-
-    if (quant > 1)
-	return -1; /* Unsupported quantization */
-
-    avctx->sample_rate = dv_audio_frequency[freq];
-    avctx->channels = 2;
-    avctx->bit_rate = avctx->channels * avctx->sample_rate * 16;
-    // What about:
-    // avctx->frame_size =
-   
-    *data_size = (dv_audio_min_samples[sys][freq] + smpls) * 
-	         avctx->channels * 2;
-
-    if (sys) {
-	nb_dif_segs = 12;
-	stride = 108;
-	unshuffle = dv_place_audio50;
-    } else {
-	nb_dif_segs = 10;
-	stride = 90;
-	unshuffle = dv_place_audio60;
-    }
-    
-    /* for each DIF segment */
-    buf_ptr = buf;
-    for (difseg = 0; difseg < nb_dif_segs; difseg++) {
-         buf_ptr += 6 * 80; /* skip DIF segment header */
-         for (ad = 0; ad < 9; ad++) {
-              
-              for (dp = 8; dp < 80; dp+=2) {
-		   if (quant == 0) {  /* 16bit quantization */
-		       i = unshuffle[difseg][ad] + (dp - 8)/2 * stride;
-		       ((short *)data)[i] = (buf_ptr[dp] << 8) | buf_ptr[dp+1]; 
-		       if (((unsigned short *)data)[i] == 0x8000)
-		           ((short *)data)[i] = 0;
-		   } else {           /* 12bit quantization */
-		       if (difseg >= nb_dif_segs/2)
-			   goto out;  /* We're not doing 4ch at this time */
-		       
-		       lc = ((uint16_t)buf_ptr[dp] << 4) | 
-			    ((uint16_t)buf_ptr[dp+2] >> 4);
-		       rc = ((uint16_t)buf_ptr[dp+1] << 4) |
-			    ((uint16_t)buf_ptr[dp+2] & 0x0f);
-		       lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
-		       rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
-
-		       i = unshuffle[difseg][ad] + (dp - 8)/3 * stride;
-		       ((short *)data)[i] = lc;
-		       i = unshuffle[difseg+nb_dif_segs/2][ad] + (dp - 8)/3 * stride;
-		       ((short *)data)[i] = rc;
-		       ++dp;
-		   }
-	      }
-		
-	    buf_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
-        }
-    }
-
-out:
-    return buf_size;
-}
-
-static int dvaudio_decode_end(AVCodecContext *avctx)
-{
-    //    DVAudioDecodeContext *s = avctx->priv_data;
-    return 0;
-}
-
-AVCodec dvaudio_decoder = {
-    "dvaudio",
-    CODEC_TYPE_AUDIO,
-    CODEC_ID_DVAUDIO,
-    sizeof(DVAudioDecodeContext),
-    dvaudio_decode_init,
-    NULL,
-    dvaudio_decode_end,
-    dvaudio_decode_frame,
-    0,
-    NULL
-};
--- a/dvdata.h	Mon Sep 29 15:44:59 2003 +0000
+++ b/dvdata.h	Mon Sep 29 17:54:07 2003 +0000
@@ -21,11 +21,34 @@
  * @file dvdata.h
  * Constants for DV codec.
  */
- 
+
+/* 
+ * DVprofile is used to express the differences between various 
+ * DV flavors. For now it's primarily used for differentiating
+ * 525/60 and 625/50, but the plans are to use it for various
+ * DV specs as well (e.g. SMPTE314M vs. IEC 61834).
+ */
+typedef struct DVprofile {
+    int              dsf;                 /* value of the dsf in the DV header */
+    int              frame_size;          /* total size of one frame in bytes */
+    int              difseg_size;         /* number of DIF segments */
+    int              frame_rate;      
+    int              frame_rate_base;
+    int              ltc_divisor;         /* FPS from the LTS standpoint */
+    int              height;              /* picture height in pixels */
+    int              width;               /* picture width in pixels */
+    const uint16_t  *video_place;         /* positions of all DV macro blocks */
+    enum PixelFormat pix_fmt;             /* picture pixel format */
+    
+    int              audio_stride;        /* size of audio_shuffle table */
+    int              audio_min_samples[3];/* min ammount of audio samples */
+                                          /* for 48Khz, 44.1Khz and 32Khz */
+    int              audio_samples_dist[5];/* how many samples are supposed to be */
+                                         /* in each frame in a 5 frames window */
+    const uint16_t (*audio_shuffle)[9];  /* PCM shuffling table */
+} DVprofile;
+
 #define NB_DV_VLC 409
-#define AAUX_AS_OFFSET  (80*6 + 80*16*3 + 3)
-#define AAUX_ASC_OFFSET (80*6 + 80*16*4 + 3)
-#define VAUX_TC61_OFFSET (80*5 + 48 + 5)
 
 static const uint16_t dv_vlc_bits[409] = {
  0x0000, 0x0002, 0x0007, 0x0008, 0x0009, 0x0014, 0x0015, 0x0016,
@@ -283,7 +306,7 @@
     1,2,2,3,3,3,3,3,
 };
 
-static uint8_t dv_quant_shifts[22][4] = {
+static const uint8_t dv_quant_shifts[22][4] = {
   { 3,3,4,4 }, 
   { 3,3,4,4 }, 
   { 2,3,3,4 }, 
@@ -1240,7 +1263,7 @@
  0x0834, 0x2320, 0x2f44, 0x3810, 0x1658,
 };
 
-static const uint16_t dv_place_audio60[10][9] = {
+static const uint16_t dv_audio_shuffle525[10][9] = {
   {  0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */
   {  6, 36, 66, 26, 56, 86, 16, 46, 76 },
   { 12, 42, 72,  2, 32, 62, 22, 52, 82 },
@@ -1254,7 +1277,7 @@
   { 25, 55, 85, 15, 45, 75,  5, 35, 65 },
 };
 
-static const uint16_t dv_place_audio50[12][9] = {
+static const uint16_t dv_audio_shuffle625[12][9] = {
   {   0,  36,  72,  26,  62,  98,  16,  52,  88}, /* 1st channel */
   {   6,  42,  78,  32,  68, 104,  22,  58,  94},
   {  12,  48,  84,   2,  38,  74,  28,  64, 100},
@@ -1271,10 +1294,77 @@
 };
 
 static const int dv_audio_frequency[3] = {
-    48000, 44100, 32000, 
+    48000, 44100, 32000,
+};
+    
+static const DVprofile dv_profiles[] = {
+    { .dsf = 0,
+      .frame_size = 120000,        /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */
+      .difseg_size = 10,
+      .frame_rate = 30000,
+      .ltc_divisor = 30,
+      .frame_rate_base = 1001,
+      .height = 480,
+      .width = 720,
+      .video_place = dv_place_411,
+      .pix_fmt = PIX_FMT_YUV411P,
+      .audio_stride = 90,
+      .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32Khz */
+      .audio_samples_dist = { 1602, 1601, 1602, 1601, 1602 },
+      .audio_shuffle = dv_audio_shuffle525,
+    }, 
+    { .dsf = 1,
+      .frame_size = 144000,        /* IEC 61834 - 625/50 (PAL) */
+      .difseg_size = 12,
+      .frame_rate = 25,
+      .frame_rate_base = 1,
+      .ltc_divisor = 25,
+      .height = 576,
+      .width = 720,
+      .video_place = dv_place_420,
+      .pix_fmt = PIX_FMT_YUV420P,
+      .audio_stride = 108,
+      .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32Khz */
+      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
+      .audio_shuffle = dv_audio_shuffle625,
+    },
+    { .dsf = 1,
+      .frame_size = 144000,        /* SMPTE-314M - 625/50 (PAL) */
+      .difseg_size = 12,
+      .frame_rate = 25,
+      .frame_rate_base = 1,
+      .ltc_divisor = 25,
+      .height = 576,
+      .width = 720,
+      .video_place = dv_place_411P,
+      .pix_fmt = PIX_FMT_YUV411P,
+      .audio_stride = 108,
+      .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32Khz */
+      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
+      .audio_shuffle = dv_audio_shuffle625,
+     }
 };
 
-static const int dv_audio_min_samples[2][3] = {
-    { 1580, 1452, 1053 }, /* 60 fields */
-    { 1896, 1742, 1264 }, /* 50 fileds */
-};
+static inline const DVprofile* dv_frame_profile(uint8_t* frame)
+{
+    if ((frame[3] & 0x80) == 0) {      /* DSF flag */
+        return &dv_profiles[0];
+    }
+    else if ((frame[5] & 0x07) == 0) { /* APT flag */
+        return &dv_profiles[1];
+    }
+    else 
+        return &dv_profiles[2];
+}
+
+static inline const DVprofile* dv_codec_profile(AVCodecContext* codec)
+{
+    if (codec->width != 720) {
+        return NULL;
+    } 
+    else if (codec->height == 480) {
+        return &dv_profiles[0];
+    } 
+    else 
+        return &dv_profiles[1];
+}