summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/import/decode_dv.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/decode_dv.c')
-rw-r--r--debian/transcode/transcode-1.1.7/import/decode_dv.c615
1 files changed, 615 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/decode_dv.c b/debian/transcode/transcode-1.1.7/import/decode_dv.c
new file mode 100644
index 00000000..0026924e
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/import/decode_dv.c
@@ -0,0 +1,615 @@
+/*
+ * decode_dv.c - Digital Video decoding routines, using libdv
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "tcinfo.h"
+#include "libtcvideo/tcvideo.h"
+#include "ioaux.h" /* for import_exit() prototype */
+#include "tc.h" /* for function prototypes */
+
+#ifdef HAVE_LIBDV
+# include <libdv/dv.h>
+#endif
+
+#define DV_FRAME_SIZE_525_60 120000
+#define DV_FRAME_SIZE_625_50 144000
+
+/* Redefine libdv constants to match our naming style */
+#define DV_SYSTEM_525_60 e_dv_system_525_60
+#define DV_SYSTEM_625_50 e_dv_system_625_50
+#define DV_COLOR_YUV e_dv_color_yuv
+#define DV_COLOR_RGB e_dv_color_rgb
+
+/*************************************************************************/
+
+#ifdef HAVE_LIBDV
+
+/**
+ * check_yuy2: Internal routine to check whether libdv returns YUY2 or
+ * YV12 data for PAL DV frames.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * 1 if the decoded video data is in YUY2 format,
+ * 0 if the decoded video data is in YV12 format,
+ * -1 if the decoded video data format is unknown.
+ */
+
+static int check_yuy2(void)
+{
+ static uint8_t dv_frame[12][150][80]; /* Input DV frame (generated) */
+ static uint8_t Y[720*576*2]; /* Output Y/YUY2 plane */
+ static uint8_t U[(720/2)*(576/2)]; /* Output U plane */
+ static uint8_t V[(720/2)*(576/2)]; /* Output V plane */
+ uint8_t *video[3] = {Y, U, V};
+ int linesize[3] = {720*2, 720/2, 720/2};
+ dv_decoder_t *decoder;
+ int i, j, k;
+
+ /* Generate an off-white PAL DV frame (Y=0xD0 U/V=0x80) */
+ for (i = 0; i < 12; i++) {
+ dv_frame[i][0][0] = 0x1F;
+ dv_frame[i][0][1] = i<<4 | 0x07;
+ dv_frame[i][0][2] = 0x00;
+ dv_frame[i][0][3] = 0xBF;
+ dv_frame[i][0][4] = 0x68;
+ dv_frame[i][0][5] = 0x78;
+ dv_frame[i][0][6] = 0x78;
+ dv_frame[i][0][7] = 0x78;
+ memset(&dv_frame[i][0][8], 0xFF, 72);
+ for (j = 0; j < 2; j++) {
+ dv_frame[i][j+1][0] = 0x3F;
+ dv_frame[i][j+1][1] = i<<4 | 0x07;
+ dv_frame[i][j+1][2] = j;
+ dv_frame[i][j+1][3] = (i>=6 ? 0x80 : 0) | ((i+12) >> 3);
+ dv_frame[i][j+1][4] = ((i+12) << 5) | (j*6);
+ memset(&dv_frame[i][j+1][5], 0xFF, 75);
+ }
+ for (j = 0; j < 3; j++) {
+ dv_frame[i][j+3][0] = 0x5F;
+ dv_frame[i][j+3][1] = i<<4 | 0x07;
+ dv_frame[i][j+3][2] = j;
+ memset(&dv_frame[i][j+3][3], 0xFF, 77);
+ if (i == 0 && j == 0) {
+ dv_frame[i][j+3][ 3] = 0x70;
+ dv_frame[i][j+3][ 4] = 0xC5;
+ dv_frame[i][j+3][ 5] = 0x41;
+ dv_frame[i][j+3][ 6] = 0x20;
+ dv_frame[i][j+3][ 7] = 0xFF;
+ dv_frame[i][j+3][ 8] = 0x71;
+ dv_frame[i][j+3][ 9] = 0xFF;
+ dv_frame[i][j+3][10] = 0x7F;
+ dv_frame[i][j+3][11] = 0xFF;
+ dv_frame[i][j+3][12] = 0xFF;
+ dv_frame[i][j+3][13] = 0x7F;
+ dv_frame[i][j+3][14] = 0xFF;
+ dv_frame[i][j+3][15] = 0xFF;
+ dv_frame[i][j+3][16] = 0x38;
+ dv_frame[i][j+3][17] = 0x81;
+ } else if (j == 2) {
+ dv_frame[i][j+3][48] = 0x60;
+ dv_frame[i][j+3][48] = 0xFF;
+ dv_frame[i][j+3][48] = 0xFF;
+ dv_frame[i][j+3][48] = 0x20;
+ dv_frame[i][j+3][48] = 0xFF;
+ dv_frame[i][j+3][48] = 0x61;
+ dv_frame[i][j+3][48] = 0x33;
+ dv_frame[i][j+3][48] = 0xC8;
+ dv_frame[i][j+3][48] = 0xFD;
+ dv_frame[i][j+3][48] = 0xFF;
+ }
+ }
+ for (j = 0; j < 9; j++) {
+ dv_frame[i][j*16+6][0] = 0x7B;
+ dv_frame[i][j*16+6][1] = i<<4 | 0x07;
+ dv_frame[i][j*16+6][2] = j;
+ if (j == 0) {
+ dv_frame[i][j*16+6][3] = 0x50;
+ dv_frame[i][j*16+6][4] = 0xD8;
+ dv_frame[i][j*16+6][5] = i>=6 ? 0x01 : 0x00;
+ dv_frame[i][j*16+6][6] = 0xE0;
+ dv_frame[i][j*16+6][7] = 0xC0;
+ } else if (j == 1) {
+ dv_frame[i][j*16+6][3] = 0x51;
+ dv_frame[i][j*16+6][4] = 0x33;
+ dv_frame[i][j*16+6][5] = 0xCF;
+ dv_frame[i][j*16+6][6] = 0xA0;
+ dv_frame[i][j*16+6][7] = 0xFF;
+ } else {
+ dv_frame[i][j*16+6][3] = 0xFF;
+ dv_frame[i][j*16+6][4] = 0xFF;
+ dv_frame[i][j*16+6][5] = 0xFF;
+ dv_frame[i][j*16+6][6] = 0xFF;
+ dv_frame[i][j*16+6][7] = 0xFF;
+ }
+ memset(&dv_frame[i][j*16+6][8], 0, 72);
+ for (k = 0; k < 15; k++) {
+ dv_frame[i][j*16+k+7][0] = 0x9B;
+ dv_frame[i][j*16+k+7][1] = i<<4 | 0x07;
+ dv_frame[i][j*16+k+7][2] = j*15 + k;
+ dv_frame[i][j*16+k+7][3] = 0x0F;
+ memset(&dv_frame[i][4], 0, 76);
+ dv_frame[i][j*16+k+7][ 4] = 0x50;
+ dv_frame[i][j*16+k+7][ 5] = 0x06;
+ dv_frame[i][j*16+k+7][18] = 0x50;
+ dv_frame[i][j*16+k+7][19] = 0x06;
+ dv_frame[i][j*16+k+7][32] = 0x50;
+ dv_frame[i][j*16+k+7][33] = 0x06;
+ dv_frame[i][j*16+k+7][46] = 0x50;
+ dv_frame[i][j*16+k+7][47] = 0x06;
+ dv_frame[i][j*16+k+7][61] = 0x16;
+ dv_frame[i][j*16+k+7][71] = 0x26;
+ }
+ }
+ }
+
+ /* Decode the generated frame */
+ decoder = dv_decoder_new(1, 0, 0);
+ if (!decoder) {
+ if (verbose & TC_DEBUG) {
+ tc_log_warn(__FILE__,
+ "check_yuy2: Unable to initialize DV decoder");
+ }
+ return -1;
+ }
+ decoder->quality = DV_QUALITY_BEST;
+ if (dv_parse_header(decoder, (uint8_t *)dv_frame) < 0) {
+ if (verbose & TC_DEBUG) {
+ tc_log_warn(__FILE__,
+ "check_yuy2: Parsing test DV frame header failed");
+ }
+ return -1;
+ }
+ dv_decode_full_frame(decoder, (uint8_t *)dv_frame, DV_COLOR_YUV,
+ video, linesize);
+ dv_decoder_free(decoder);
+
+ /* Return whether the frame is YUY2-encoded or not */
+ if (Y[0] >= 0xCF && Y[0] <= 0xD1) {
+ if (Y[1] >= 0xCF && Y[1] <= 0xD1) {
+ /* Planar YUV data */
+ return 0;
+ } else if (Y[1] >= 0x7F && Y[1] <= 0x81) {
+ /* Packed YUY2 data */
+ return 1;
+ }
+ }
+ /* Else a buggy library? */
+ if (verbose & TC_DEBUG) {
+ tc_log_warn(__FILE__,
+ "check_yuy2: Bad video data (Y=%02X %02X %02X %02X,"
+ " U=%02X %02X, V=%02X %02X)", Y[0], Y[1], Y[2], Y[3],
+ U[0], U[1], V[0], V[1]);
+ }
+
+ return -1;
+}
+
+#endif // HAVE_LIBDV
+
+/*************************************************************************/
+
+/**
+ * decode_dv: DV decoding loop, called from tcdecode. Reads raw DV frames
+ * from stdin and writes the decoded video or audio data to stdout.
+ *
+ * Parameters:
+ * decode: Pointer to decoding parameter structure.
+ * Return value:
+ * None.
+ */
+
+void decode_dv(decode_t *decode)
+{
+#ifdef HAVE_LIBDV
+
+ dv_decoder_t *decoder;
+ /* FIXME: should this buffer be static instead (to reduce stack usage)? */
+ uint8_t framebuf[DV_FRAME_SIZE_625_50]; /* Buffer for input frame */
+ uint8_t *video[3]; /* Decoded video data */
+ uint8_t *video_conv_buf[3]; /* For YUY2/420P conversion */
+ TCVHandle tcvhandle; /* For YUY2/420P conversion */
+ ImageFormat srcfmt = 0, destfmt = 0; /* For YUY2/420P conversion */
+ dv_color_space_t colorspace = 0; /* For dv_decode_full_frame() */
+ int linesize[3], planesize[3]; /* video[] line/plane size */
+ int video_conv_linesize[3]; /* Same, for video_conv_buf[] */
+ int16_t audio_in[4][DV_AUDIO_MAX_SAMPLES]; /* Decoded audio data */
+ int16_t *audio_inptr[4]; /* List of pointers for same */
+ int16_t audio_out[4*DV_AUDIO_MAX_SAMPLES]; /* Interleaved audio data */
+ int yuy2_mode; /* libdv YUY2/YV12 selector */
+ int error = 0; /* Set to signal an error */
+ int ispal; /* Is it a 625/50 stream? */
+ int nread; /* Result of tc_pread() */
+
+
+ /**** Sanity check and variable setup ****/
+
+ if (!decode) {
+ tc_log_error(__FILE__, "Invalid parameter to decode_dv()");
+ import_exit(1);
+ return;
+ }
+ audio_inptr[0] = audio_in[0];
+ audio_inptr[1] = audio_in[1];
+ audio_inptr[2] = audio_in[2];
+ audio_inptr[3] = audio_in[3];
+
+ /**** Initialize libtcvideo for potential image format conversion ****/
+
+ tcvhandle = tcv_init();
+ if (!tcvhandle) {
+ tc_log_error(__FILE__, "Unable to initialize libtcvideo");
+ import_exit(1);
+ return;
+ }
+
+ /**** Initialize libdv decoder ****/
+
+ decoder = dv_decoder_new(1, 0, 0);
+ if (!decoder) {
+ tc_log_error(__FILE__, "Unable to initialize DV decoder");
+ import_exit(1);
+ return;
+ }
+ switch (decode->quality) {
+ case 1: decoder->quality = DV_QUALITY_FASTEST; break;
+ case 2: decoder->quality = DV_QUALITY_AC_1; break;
+ case 3: decoder->quality = DV_QUALITY_AC_2; break;
+ case 4: decoder->quality = DV_QUALITY_AC_1 | DV_QUALITY_COLOR; break;
+ case 5:
+ default: decoder->quality = DV_QUALITY_BEST; break;
+ }
+
+ /**** Set up image formats and line size per plane (*16) ****/
+
+ switch (decode->format) {
+ case TC_CODEC_YUV420P:
+ srcfmt = IMG_UNKNOWN; /* Source format not yet known */
+ destfmt = IMG_YUV420P;
+ colorspace = DV_COLOR_YUV;
+ linesize[0] = 16;
+ linesize[1] = linesize[2] = 8;
+ break;
+ case TC_CODEC_YUY2:
+ srcfmt = IMG_UNKNOWN; /* Source format not yet known */
+ destfmt = IMG_YUY2;
+ colorspace = DV_COLOR_YUV;
+ linesize[0] = 32;
+ linesize[1] = linesize[2] = 0;
+ break;
+ case TC_CODEC_RGB:
+ srcfmt = destfmt = IMG_RGB24;
+ colorspace = DV_COLOR_RGB;
+ linesize[0] = 48;
+ linesize[1] = linesize[2] = 0;
+ break;
+ case TC_CODEC_PCM:
+ linesize[0] = linesize[1] = linesize[2] = 0; // what video? ;)
+ break;
+ default:
+ tc_log_error(__FILE__, "Invalid output format (%08lX)",
+ decode->format);
+ import_exit(1);
+ return;
+ }
+
+ /**** Read the first frame and analyze the frame header. We start ****
+ **** by reading in enough data for an NTSC frame; if it turns out ****
+ **** to be PAL instead, we read the rest of it once we find that ****
+ **** out. ****/
+
+ nread = tc_pread(decode->fd_in, framebuf, DV_FRAME_SIZE_525_60);
+ if (nread != DV_FRAME_SIZE_525_60) {
+ tc_log_error(__FILE__, "No DV frames found!");
+ import_exit(1);
+ return;
+ }
+ if (dv_parse_header(decoder, framebuf) < 0) {
+ tc_log_error(__FILE__, "Unable to parse frame header!");
+ import_exit(1);
+ return;
+ }
+ if (decoder->system == DV_SYSTEM_525_60) {
+ ispal = 0;
+ } else if (decoder->system == DV_SYSTEM_625_50) {
+ ispal = 1;
+ } else {
+ tc_log_error(__FILE__, "Unknown or invalid DV frame type!");
+ import_exit(1);
+ return;
+ }
+ if (ispal) {
+ nread = tc_pread(decode->fd_in, framebuf + DV_FRAME_SIZE_525_60,
+ DV_FRAME_SIZE_625_50 - DV_FRAME_SIZE_525_60);
+ if (nread != DV_FRAME_SIZE_625_50 - DV_FRAME_SIZE_525_60) {
+ tc_log_error(__FILE__, "No DV frames found!");
+ import_exit(1);
+ return;
+ }
+ }
+
+ /**** Print a stream information summary ****/
+
+ if (verbose) {
+ if (decode->format == TC_CODEC_PCM) {
+ tc_log_info(__FILE__, "audio: %d Hz, %d channels",
+ decoder->audio->frequency,
+ decoder->audio->num_channels);
+ } else {
+ tc_log_info(__FILE__, "%s video: %dx%d framesize=%lu sampling=%d",
+ ispal ? "PAL" : "NTSC", decoder->width,
+ decoder->height, (unsigned long)decoder->frame_size,
+ decoder->sampling);
+ }
+ }
+
+ /**** Allocate video buffers ****/
+
+ /* Plane 0: packed RGB, packed YUV, or planar Y */
+ linesize[0] = (linesize[0] * decoder->width) / 16;
+ planesize[0] = linesize[0] * decoder->height;
+
+ /* Plane 1: planar U (half height) */
+ linesize[1] = (linesize[1] * decoder->width) / 16;
+ planesize[1] = linesize[1] * (decoder->height/2);
+
+ /* Plane 2: planar V (half height) */
+ linesize[2] = (linesize[2] * decoder->width) / 16;
+ planesize[2] = linesize[2] * (decoder->height/2);
+
+ /* Set up pointers into a contiguous buffer */
+ video[0] = tc_bufalloc(planesize[0] + planesize[1] + planesize[2]);
+ video[1] = video[0] + planesize[0];
+ video[2] = video[1] + planesize[1];
+
+ /* Conversion buffer (allocate just in case) */
+ video_conv_buf[0] = tc_bufalloc(decoder->width * decoder->height * 2);
+ video_conv_buf[1] = video_conv_buf[0] + decoder->width * decoder->height;
+ video_conv_buf[2] = video_conv_buf[1] + (decoder->width/2)*decoder->height;
+
+ /* Make sure we got everything we need */
+ if (!video[0] || !video_conv_buf[0]) {
+ tc_log_error(__FILE__, "No memory for video buffers!");
+ tc_buffree(video_conv_buf[0]);
+ tc_buffree(video[0]);
+ import_exit(1);
+ return;
+ }
+
+ /**** Determine whether YUV data is YUY2 or YV12 (really I420??) ****/
+
+ if (ispal) {
+ if (decode->dv_yuy2_mode != -1) {
+ /* User specified --dv_yuy2_mode or --dv_yv12_mode */
+ yuy2_mode = decode->dv_yuy2_mode;
+ } else {
+ int result = check_yuy2();
+ if (result >= 1)
+ yuy2_mode = result;
+ else /* we don't know, use the libdv default of YUY2 as a guess */
+ yuy2_mode = 1;
+ }
+ } else {
+ /* NTSC is always returned in YUY2 format */
+ yuy2_mode = 1;
+ }
+ if (srcfmt == IMG_UNKNOWN) {
+ if (yuy2_mode) {
+ srcfmt = IMG_YUY2;
+ video_conv_linesize[0] = decoder->width * 2;
+ video_conv_linesize[1] = video_conv_linesize[2] = 0;
+ } else {
+ srcfmt = IMG_YUV420P;
+ video_conv_linesize[0] = decoder->width;
+ video_conv_linesize[1] = video_conv_linesize[2] = decoder->width/2;
+ }
+ }
+
+ /**** Decoding loop ****/
+
+ for (;;) {
+ int toread;
+
+ /* Process the data as requested */
+
+ switch (decode->format) {
+
+ case TC_CODEC_YUV420P:
+ case TC_CODEC_YUY2:
+ case TC_CODEC_RGB:
+ if (srcfmt == destfmt) {
+ dv_decode_full_frame(decoder, framebuf, colorspace, video,
+ linesize);
+ } else {
+ dv_decode_full_frame(decoder, framebuf, colorspace,
+ video_conv_buf, video_conv_linesize);
+ if (!tcv_convert(tcvhandle, video_conv_buf[0], video[0],
+ decoder->width, decoder->height,
+ srcfmt, destfmt)) {
+ tc_log_error(__FILE__, "Image format conversion failed!");
+ error = 1;
+ goto done;
+ }
+ }
+ if ((planesize[0] && tc_pwrite(decode->fd_out, video[0],
+ planesize[0]) != planesize[0])
+ || (planesize[1] && tc_pwrite(decode->fd_out, video[1],
+ planesize[1]) != planesize[1])
+ || (planesize[2] && tc_pwrite(decode->fd_out, video[2],
+ planesize[2]) != planesize[2])
+ ) {
+ tc_log_error(__FILE__, "Write failed: %s", strerror(errno));
+ error = 1;
+ goto done;
+ }
+ break;
+
+ case TC_CODEC_PCM: {
+ int i, ch;
+ int16_t *outptr = audio_out;
+ dv_decode_full_audio(decoder, framebuf, audio_inptr);
+ for (i = 0; i < decoder->audio->samples_this_frame; i++) {
+ for (ch = 0; ch < decoder->audio->num_channels; ch++) {
+ *outptr++ = audio_in[ch][i];
+ }
+ }
+ i = decoder->audio->samples_this_frame
+ * decoder->audio->num_channels * 2;
+ if (tc_pwrite(decode->fd_out, (void *)audio_out, i) != i) {
+ tc_log_error(__FILE__, "Write failed: %s", strerror(errno));
+ error = 1;
+ goto done;
+ }
+ break;
+ } /* case TC_CODEC_PCM */
+
+ } /* switch (decode->format) */
+
+ /* Read in the next frame, if any, and parse the header */
+
+ retry:
+ toread = ispal ? DV_FRAME_SIZE_625_50 : DV_FRAME_SIZE_525_60;
+ nread = tc_pread(decode->fd_in, framebuf, toread);
+ if (nread != toread) {
+ if (verbose & TC_DEBUG)
+ tc_log_info(__FILE__, "End of stream reached.");
+ break;
+ }
+ if (dv_parse_header(decoder, framebuf) < 0) {
+ tc_log_warn(__FILE__, "Unable to parse frame header, skipping...");
+ goto retry;
+ }
+ /* Sanity check: make sure it's the same video system */
+ if (decoder->system != (ispal ? DV_SYSTEM_625_50 : DV_SYSTEM_525_60)) {
+ tc_log_error(__FILE__, "Video system (NTSC/PAL) changed"
+ " midstream! Aborting.");
+ error = 1;
+ break;
+ }
+
+ } /* end decoding loop */
+
+ /**** All done ****/
+
+ done:
+ tc_buffree(video_conv_buf[0]);
+ tc_buffree(video[0]);
+ dv_decoder_free(decoder);
+ tcv_free(tcvhandle);
+
+ import_exit(error ? 1 : 0);
+
+#else /* !HAVE_LIBDV */
+
+ tc_log_error(__FILE__, "No support for Digital Video configured - exit.");
+ import_exit(1);
+
+#endif
+}
+
+/*************************************************************************/
+
+/**
+ * probe_dv: Probe the input stream (on stdin) and set stream parameters
+ * as appropriate.
+ *
+ * Parameters: info: Pointer to stream parameter structure.
+ * Return value: None.
+ * Preconditions: None.
+ */
+
+void probe_dv(info_t *info)
+{
+#ifdef HAVE_LIBDV
+ dv_decoder_t *decoder;
+ uint8_t framebuf[DV_FRAME_SIZE_525_60]; // FIXME: too big for the stack?
+ int nread, ispal;
+#endif
+
+ if (!info) {
+ tc_log_error(__FILE__, "Invalid parameter to probe_dv()");
+ return;
+ }
+
+#ifdef HAVE_LIBDV
+
+ /* Read in an NTSC frame; for probing, this is enough for PAL as well */
+ nread = tc_pread(info->fd_in, framebuf, sizeof(framebuf));
+ if (nread < sizeof(framebuf)) {
+ tc_log_error(__FILE__, "Stream too short");
+ info->error = 1;
+ return;
+ }
+
+ /* Initialize libdv decoder */
+ decoder = dv_decoder_new(1, 0, 0);
+ if (!decoder) {
+ tc_log_error(__FILE__, "Unable to initialize DV decoder");
+ info->error = 1;
+ return;
+ }
+
+ /* Parse frame header and check video system type */
+ if (dv_parse_header(decoder, framebuf) < 0) {
+ tc_log_error(__FILE__, "No valid DV frame found");
+ info->error = 1;
+ return;
+ }
+ if (decoder->system == DV_SYSTEM_525_60) {
+ ispal = 0;
+ } else if (decoder->system == DV_SYSTEM_625_50) {
+ ispal = 1;
+ } else {
+ tc_log_error(__FILE__, "Unknown or invalid DV frame type");
+ info->error = 1;
+ return;
+ }
+
+ /* Set stream parameters */
+
+ info->probe_info->magic = ispal ? TC_MAGIC_PAL : TC_MAGIC_NTSC;
+
+ info->probe_info->width = decoder->width;
+ info->probe_info->height = decoder->height;
+ info->probe_info->fps = ispal ? PAL_FPS : NTSC_VIDEO;
+ info->probe_info->frc = ispal ? 3 : 4;
+ info->probe_info->asr = dv_format_wide(decoder) ? 3 :
+ dv_format_normal(decoder) ? 2 : 0;
+
+ info->probe_info->track[0].samplerate = decoder->audio->frequency;
+ info->probe_info->track[0].chan = decoder->audio->num_channels;
+ info->probe_info->track[0].bits = 16;
+ info->probe_info->track[0].format = CODEC_PCM;
+ info->probe_info->track[0].bitrate =
+ (decoder->audio->frequency * decoder->audio->num_channels * 16) / 1000;
+ info->probe_info->num_tracks = 1;
+
+ /* All done */
+ dv_decoder_free(decoder);
+
+#endif /* HAVE_LIBDV */
+
+ /* Even without libdv, we know this much... */
+ info->probe_info->codec = TC_CODEC_DV;
+
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */