X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Flibdv.C;fp=cinelerra-5.1%2Fcinelerra%2Flibdv.C;h=90c9f6efefbabd99fca21a4da8792e4bfcd408be;hp=0000000000000000000000000000000000000000;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b diff --git a/cinelerra-5.1/cinelerra/libdv.C b/cinelerra-5.1/cinelerra/libdv.C new file mode 100644 index 00000000..90c9f6ef --- /dev/null +++ b/cinelerra-5.1/cinelerra/libdv.C @@ -0,0 +1,320 @@ +/* + * Grabbing algorithm is from dvgrab + */ + +#include "bccmodels.h" +#include "libdv.h" + +#include +#include +#include + +#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; +} + +