--- /dev/null
+/*
+ * Grabbing algorithm is from dvgrab
+ */
+
+#include "bccmodels.h"
+#include "libdv.h"
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef USE_MMX
+#include "mmx.h"
+#endif
+
+
+#define DV_WIDTH 720
+#define DV_HEIGHT 576
+
+
+static int dv_initted = 0;
+static pthread_mutex_t dv_lock;
+
+dv_t* dv_new()
+{
+ dv_t *dv = (dv_t *)calloc(1, sizeof(dv_t));
+ if(!dv_initted)
+ {
+ pthread_mutexattr_t attr;
+ dv_initted = 1;
+// dv_init();
+ pthread_mutexattr_init(&attr);
+ pthread_mutex_init(&dv_lock, &attr);
+ }
+
+ dv->decoder = dv_decoder_new(0, 0, 0);
+ dv_set_error_log (dv->decoder, 0);
+ dv->decoder->quality = DV_QUALITY_BEST;
+ dv->decoder->prev_frame_decoded = 0;
+ dv->use_mmx = 1;
+ return dv;
+}
+
+
+int dv_delete(dv_t *dv)
+{
+ int i;
+ if(dv->decoder)
+ {
+ dv_decoder_free( dv->decoder );
+ }
+
+ if(dv->temp_video)
+ free(dv->temp_video);
+
+ if(dv->temp_audio[0])
+ {
+ for(i = 0; i < 4; i++)
+ free(dv->temp_audio[i]);
+ }
+
+ if(dv->encoder)
+ {
+ dv_encoder_free( dv->encoder );
+ }
+
+ free(dv);
+ return 0;
+}
+
+// Decodes BC_YUV422 only
+
+
+
+int dv_read_video(dv_t *dv,
+ unsigned char **output_rows,
+ unsigned char *data,
+ long bytes,
+ int color_model)
+{
+ int i;
+ int pitches[3];
+ int use_temp = color_model != BC_YUV422;
+ unsigned char *pixels[3];
+
+//printf("dv_read_video 1 %d\n", color_model);
+ pthread_mutex_lock(&dv_lock);
+ switch(bytes)
+ {
+ case DV_PAL_SIZE:
+ break;
+ case DV_NTSC_SIZE:
+ break;
+ default:
+ return 1;
+ break;
+ }
+
+ if(data[0] != 0x1f) return 1;
+
+ pitches[0] = DV_WIDTH * 2;
+ pitches[1] = 0;
+ pitches[2] = 0;
+ pixels[1] = 0;
+ pixels[2] = 0;
+
+ dv_parse_header(dv->decoder, data);
+
+ if(!use_temp)
+ {
+//printf("dv_read_video 1\n");
+ pixels[0] = output_rows[0];
+ dv_decode_full_frame(dv->decoder,
+ data,
+ e_dv_color_yuv,
+ output_rows,
+ pitches);
+//printf("dv_read_video 2\n");
+ }
+ else
+ {
+ unsigned char *temp_rows[DV_HEIGHT];
+ if(!dv->temp_video)
+ dv->temp_video = (unsigned char *)calloc(1, DV_WIDTH * DV_HEIGHT * 2);
+
+ for(i = 0; i < DV_HEIGHT; i++)
+ {
+ temp_rows[i] = dv->temp_video + i * DV_WIDTH * 2;
+ }
+
+ pixels[0] = dv->temp_video;
+//printf("dv_read_video 3 %p\n", data);
+ dv_decode_full_frame(dv->decoder,
+ data,
+ e_dv_color_yuv,
+ pixels,
+ pitches);
+//printf("dv_read_video 4\n");
+
+ BC_CModels::transfer(output_rows,
+ temp_rows,
+ output_rows[0],
+ output_rows[1],
+ output_rows[2],
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ DV_WIDTH,
+ dv->decoder->height,
+ 0,
+ 0,
+ DV_WIDTH,
+ dv->decoder->height,
+ BC_YUV422,
+ color_model,
+ 0,
+ DV_WIDTH,
+ DV_WIDTH);
+ }
+ dv->decoder->prev_frame_decoded = 1;
+ pthread_mutex_unlock(&dv_lock);
+ return 0;
+}
+
+
+
+
+
+
+int dv_read_audio(dv_t *dv,
+ unsigned char *samples,
+ unsigned char *data,
+ long size,
+ int channels,
+ int bits)
+{
+ int i, j;
+ short *samples_int16 = (short*)samples;
+ int samples_read;
+ if(channels > 4) channels = 4;
+
+// For some reason someone had problems with libdv's maxmimum audio samples
+#define MAX_AUDIO_SAMPLES 2048
+ if(!dv->temp_audio[0])
+ {
+ for(i = 0; i < 4; i++)
+ dv->temp_audio[i] = (int16_t*)calloc(1, sizeof(int16_t) * MAX_AUDIO_SAMPLES);
+ }
+
+ switch(size) {
+ case DV_PAL_SIZE: break;
+ case DV_NTSC_SIZE: break;
+ default: return 0;
+ }
+
+ if(data[0] != 0x1f) return 0;
+
+ dv_parse_header(dv->decoder, data);
+ dv_decode_full_audio(dv->decoder, data, dv->temp_audio);
+ samples_read = dv->decoder->audio->samples_this_frame;
+
+ for(i = 0; i < channels; i++)
+ {
+ for(j = 0; j < samples_read; j++)
+ {
+ samples_int16[i + j * channels] = dv->temp_audio[i][j];
+ if(samples_int16[i + j * channels] == -0x8000)
+ samples_int16[i + j * channels] = 0;
+ }
+ }
+
+
+
+
+
+
+ return samples_read;
+}
+
+
+
+
+
+// Encodes BC_YUV422 only
+
+void dv_write_video(dv_t *dv,
+ unsigned char *data,
+ unsigned char **input_rows,
+ int color_model,
+ int norm)
+{
+ int encode_dv_colormodel = 0;
+
+ if(!dv->encoder)
+ {
+ dv->encoder = dv_encoder_new(
+ 0,
+ 0,
+ 0);
+ }
+
+ switch( color_model )
+ {
+ case BC_YUV422:
+ encode_dv_colormodel = e_dv_color_yuv;
+ break;
+ case BC_RGB888:
+ encode_dv_colormodel = e_dv_color_rgb;
+ break;
+ default:
+ return;
+ break;
+ }
+ dv->encoder->is16x9 = 0;
+ dv->encoder->vlc_encode_passes = 3;
+ dv->encoder->static_qno = 0;
+ dv->encoder->force_dct = DV_DCT_AUTO;
+ dv->encoder->isPAL = (norm == DV_PAL);
+
+ dv_encode_full_frame( dv->encoder,
+ input_rows,
+ (dv_color_space_t)encode_dv_colormodel,
+ data );
+}
+
+
+
+int dv_write_audio(dv_t *dv,
+ unsigned char *data,
+ unsigned char *input_samples,
+ int max_samples,
+ int channels,
+ int bits,
+ int rate,
+ int norm)
+{
+ int i, j;
+
+ if(!dv->encoder)
+ {
+ dv->encoder = dv_encoder_new(
+ 0,
+ 0,
+ 0 );
+ }
+ dv->encoder->isPAL = (norm == DV_PAL);
+
+
+// Get sample count from a libdv function
+ int samples = dv_calculate_samples(dv->encoder, rate, dv->audio_frames);
+ dv->audio_frames++;
+
+ if(!dv->temp_audio[0])
+ {
+ for(i = 0; i < 4; i++)
+ dv->temp_audio[i] = (int16_t*)calloc(1, sizeof(int16_t) * MAX_AUDIO_SAMPLES);
+ }
+
+ for(i = 0; i < channels; i++)
+ {
+ short *temp_audio = dv->temp_audio[i];
+ short *input_channel = (short*)input_samples + i;
+ for(j = 0; j < samples; j++)
+ {
+ temp_audio[j] = input_channel[j * channels];
+ }
+ }
+
+
+ dv_encode_full_audio(dv->encoder,
+ dv->temp_audio,
+ channels,
+ rate,
+ data);
+ return samples;
+}
+
+