minor improvements from Andrew
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / filedv.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2004 Richard Baverstock
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #ifdef HAVE_DV
23
24 #include "asset.h"
25 #include "bcsignals.h"
26 #include "byteorder.h"
27 #include "dv1394.h"
28 #include "edit.h"
29 #include "file.h"
30 #include "filedv.h"
31 #include "guicast.h"
32 #include "interlacemodes.h"
33 #include "language.h"
34 #include "mutex.h"
35 #include "mwindow.inc"
36 #include "vframe.h"
37 #include "videodevice.inc"
38 #include "mainerror.h"
39
40
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <errno.h>
48
49 #include <iostream>
50
51 FileDV::FileDV(Asset *asset, File *file)
52  : FileBase(asset, file)
53 {
54         stream = 0;
55         decoder = 0;
56         encoder = 0;
57         audio_encoder = 0;
58         audio_buffer = 0;
59         video_buffer = 0;
60         output_size = 0;
61         video_position = 0;
62         audio_position = 0;
63
64         audio_sample_buffer = 0;
65         audio_sample_buffer_len = 0;
66         audio_sample_buffer_start = 0;
67         audio_sample_buffer_end = 0;
68         audio_sample_buffer_maxsize = 0;
69
70         audio_frames_written = 0;
71
72         if(asset->format == FILE_UNKNOWN)
73                 asset->format = FILE_RAWDV;
74         asset->byte_order = 0;
75
76         stream_lock = new Mutex("FileDV::stream_lock");
77         decoder_lock = new Mutex("FileDV::decoder_lock");
78         video_position_lock = new Mutex("FileDV::video_position_lock");
79 }
80
81 FileDV::~FileDV()
82 {
83         if(stream) close_file();
84
85         if(decoder) dv_decoder_free(decoder);
86         if(encoder) dv_encoder_free(encoder);
87         if(audio_encoder) dv_encoder_free(audio_encoder);
88
89         delete stream_lock;
90         delete decoder_lock;
91         delete video_position_lock;
92
93         delete[] video_buffer;
94         delete[] audio_buffer;
95
96         if(audio_sample_buffer)
97         {
98                 for(int i = 0; i < asset->channels; i++)
99                         delete[] audio_sample_buffer[i];
100                 delete[] audio_sample_buffer;
101         }
102 }
103
104 void FileDV::get_parameters(BC_WindowBase *parent_window,
105         Asset *asset, BC_WindowBase* &format_window,
106         int audio_options, int video_options, EDL *edl)
107 {
108         if(audio_options)
109         {
110                 DVConfigAudio *window = new DVConfigAudio(parent_window, asset);
111                 format_window = window;
112                 window->create_objects();
113                 window->run_window();
114                 delete window;
115         }
116         else
117         if(video_options)
118         {
119                 DVConfigVideo *window = new DVConfigVideo(parent_window, asset);
120                 format_window = window;
121                 window->create_objects();
122                 window->run_window();
123                 delete window;
124         }
125
126 }
127
128 int FileDV::reset_parameters_derived()
129 {
130         if(decoder) dv_decoder_free(decoder);
131         if(encoder) dv_encoder_free(encoder);
132         if(audio_encoder) dv_encoder_free(audio_encoder);
133         decoder = 0;
134         encoder = 0;
135         audio_encoder = 0;
136
137 TRACE("FileDV::reset_parameters_derived 10")
138
139 TRACE("FileDV::reset_parameters_derived: 20")
140         delete[] audio_buffer;
141         delete[] video_buffer;
142 TRACE("FileDV::reset_parameters_derived: 30")
143
144         audio_buffer = 0;
145         video_buffer = 0;
146
147         if(stream) fclose(stream);
148
149         stream = 0;
150
151         audio_position = 0;
152         video_position = 0;
153
154         if(audio_sample_buffer)
155         {
156                 for(int i = 0; i < asset->channels; i++)
157                         delete[] audio_sample_buffer[i];
158                 delete[] audio_sample_buffer;
159         }
160         audio_sample_buffer = 0;
161         audio_sample_buffer_start = 0;
162         audio_sample_buffer_len = 0;
163         audio_sample_buffer_end = 0;
164         audio_sample_buffer_maxsize = 0;
165
166         audio_frames_written = 0;
167 // output_size gets set in open_file, once we know if the frames are PAL or NTSC
168 // output and input are allocated at the same point.
169         output_size = 0;
170
171 UNTRACE
172         return 0;
173 }
174
175 int FileDV::open_file(int rd, int wr)
176 {
177
178 TRACE("FileDV::open_file 10")
179
180         if(wr)
181         {
182
183 TRACE("FileDV::open_file 20")
184
185
186                 if (!(asset->height == 576 && asset->width == 720 && asset->frame_rate == 25) &&
187                     !(asset->height == 480 && asset->width == 720 && (asset->frame_rate >= 29.96 && asset->frame_rate <= 29.98)))
188                 {
189                         eprintf(_("Raw DV format does not support following resolution: %ix%i framerate: %f\nAllowed resolutions are 720x576 25fps (PAL) and 720x480 29.97fps (NTSC)\n"), asset->width, asset->height, asset->frame_rate);
190                         if (asset->height == 480 && asset->width == 720 && asset->frame_rate == 30)
191                         {
192                                 eprintf(_("Suggestion: Proper frame rate for NTSC DV is 29.97 fps, not 30 fps\n"));
193                         }
194                         return 1;
195                 }
196                 if (!(asset->channels == 2 && (asset->sample_rate == 48000 || asset->sample_rate == 44100)) &&
197                     !((asset->channels == 4 || asset->channels == 2) && asset->sample_rate == 32000))
198                 {
199                         eprintf(_("Raw DV format does not support following audio configuration : %i channels at sample rate: %iHz\n"), asset->channels, asset->sample_rate);
200                         return 1;
201                 }
202
203
204                 if((stream = fopen(asset->path, "w+b")) == 0)
205                 {
206                         eprintf(_("Error while opening \"%s\" for writing. \n%m\n"), asset->path);
207                         return 1;
208                 }
209
210                 // Create a new encoder
211                 if(encoder) dv_encoder_free(encoder);
212                 encoder = dv_encoder_new(0,0,0);
213                 encoder->vlc_encode_passes = 3;
214                 encoder->static_qno = 0;
215                 encoder->force_dct = DV_DCT_AUTO;
216
217                 if(audio_encoder) dv_encoder_free(audio_encoder);
218                 audio_encoder = dv_encoder_new(0, 0, 0);
219                 audio_encoder->vlc_encode_passes = 3;
220                 audio_encoder->static_qno = 0;
221                 audio_encoder->force_dct = DV_DCT_AUTO;
222
223                 if(decoder) dv_decoder_free(decoder);
224                 decoder = dv_decoder_new(0,0,0);
225                 decoder->quality = DV_QUALITY_BEST;
226
227
228                 isPAL = (asset->height == 576 ? 1 : 0);
229                 encoder->isPAL = isPAL;
230                 output_size = (isPAL ? DV1394_PAL_FRAME_SIZE : DV1394_NTSC_FRAME_SIZE);
231
232                 // Compare to 16 / 8 rather than == 16 / 9 in case of floating point
233                 // rounding errors
234                 encoder->is16x9 = asset->aspect_ratio > 16 / 8;
235         }
236         else
237         {
238                 unsigned char *temp;
239
240 TRACE("FileDV::open_file 30")
241
242                 struct stat info;
243
244 TRACE("FileDV::open_file 40")
245
246                 if((stream = fopen(asset->path, "rb")) == 0)
247                 {
248                         eprintf(_("Error while opening \"%s\" for reading. \n%m\n"), asset->path);
249                         return 1;
250                 }
251
252                 // temp storage to find out the correct info from the stream.
253                 temp = new unsigned char[DV1394_PAL_FRAME_SIZE];
254                 memset(temp, 0, DV1394_PAL_FRAME_SIZE);
255
256                 // need file size info to get length.
257                 stat(asset->path, &info);
258
259 TRACE("FileDV::open_file 50")
260
261                 // read the first frame so we can get the stream info from it
262                 // by reading the greatest possible frame size, we ensure we get all the
263                 // data. libdv will determine if it's PAL or NTSC, and input and output
264                 // buffers get allocated accordingly.
265                 fread(temp, DV1394_PAL_FRAME_SIZE, 1, stream);
266
267 TRACE("FileDV::open_file 60")
268
269                 if(decoder) dv_decoder_free(decoder);
270                 decoder = dv_decoder_new(0,0,0);
271                 decoder->quality = DV_QUALITY_BEST;
272
273
274                 if(dv_parse_header(decoder, temp) > -1 )
275                 {
276                         // define video params first -- we need to find out output_size
277                         // always have video
278                         asset->video_data = 1;
279                         asset->layers = 1;
280
281                         //TODO: according to the information I found, letterbox and widescreen
282                         //are the same thing; however, libdv provides a function to check
283                         //if the video feed is one of the other. Need to find out if there
284                         //is a difference.
285                         if(dv_format_normal(decoder) != 0) asset->aspect_ratio = (double) 4 / 3;
286                         else asset->aspect_ratio = (double) 16 / 9;
287
288                         asset->width = decoder->width;
289                         asset->height = decoder->height;
290
291                         if(dv_is_progressive(decoder) > 0)
292                                 asset->interlace_mode = ILACE_MODE_NOTINTERLACED;
293                         else
294                                 asset->interlace_mode = ILACE_MODE_BOTTOM_FIRST;
295
296                         isPAL = dv_is_PAL(decoder);
297
298                         output_size = (isPAL ? DV1394_PAL_FRAME_SIZE : DV1394_NTSC_FRAME_SIZE);
299                         asset->video_length = info.st_size / output_size;
300
301                         if(!asset->frame_rate)
302                                 asset->frame_rate = (isPAL ? 25 : 29.97);
303                         strncpy(asset->vcodec, "dvc ", 4);
304
305                         // see if there are any audio tracks
306                         asset->channels = dv_get_num_channels(decoder);
307                         if(asset->channels > 0)
308                         {
309                                 asset->audio_data = 1;
310                                 asset->sample_rate = dv_get_frequency(decoder);
311                                 // libdv always scales the quantization up to 16 bits for dv_decode_full_audio
312                                 asset->bits = 16;
313                                 asset->audio_length = (int64_t) (info.st_size / output_size / asset->frame_rate * asset->sample_rate);
314                                 strncpy(asset->acodec, "dvc ", 4);
315                         }
316                         else
317                                 asset->audio_data = 0;
318                 }
319                 else
320                 {
321                         asset->audio_data = 0;
322                         asset->video_data = 0;
323                 }
324
325                 fseeko(stream, 0, SEEK_SET);
326 TRACE("FileDV::open_file 80")
327
328                 delete[] temp;
329         }
330
331         // allocate space for audio and video
332         video_buffer = new unsigned char[output_size + 4];
333         audio_buffer = new unsigned char[output_size + 4];
334
335 UNTRACE
336         return 0;
337 }
338
339 int FileDV::check_sig(Asset *asset)
340 {
341         unsigned char temp[3];
342         FILE *t_stream = fopen(asset->path, "rb");
343
344         fread(&temp, 3, 1, t_stream);
345
346         fclose(t_stream);
347
348         if(temp[0] == 0x1f &&
349                         temp[1] == 0x07 &&
350                         temp[2] == 0x00)
351                 return 1;
352
353         return 0;
354 }
355
356 int FileDV::close_file_derived()
357 {
358         if(stream) fclose(stream);
359         stream = 0;
360
361         return 0;
362 }
363
364 int64_t FileDV::get_video_position()
365 {
366         return video_position;
367 }
368
369 int64_t FileDV::get_audio_position()
370 {
371         return audio_position;
372 }
373
374 int FileDV::set_video_position(int64_t x)
375 {
376         video_position = x;
377         return 0;
378 }
379
380 int FileDV::set_audio_position(int64_t x)
381 {
382         audio_position = x;
383         return 0;
384 }
385
386 int FileDV::audio_samples_copy(double **buffer, int64_t len)
387 {
388         // take the buffer and copy it into a queue
389         if(!audio_sample_buffer)
390         {
391                 audio_sample_buffer = new int16_t*[asset->channels];
392                 if(!audio_sample_buffer)
393                 {
394                         fprintf(stderr, _("ERROR: Unable to allocate memory for audio_sample_buffer.\n"));
395                         return 1;
396                 }
397
398                 for(int i = 0; i < asset->channels; i++)
399                 {
400                         audio_sample_buffer[i] = new int16_t[len * 2];
401
402                         if(!audio_sample_buffer[i])
403                         {
404                                 fprintf(stderr, _("ERROR: Unable to allocate memory for "
405                                         "audio_sample_buffer channel %d\n"), i);
406                                 return 1;
407                         }
408                 }
409                 audio_sample_buffer_maxsize = len * 2;
410                 audio_sample_buffer_len = 0;
411                 audio_sample_buffer_start = 0;
412                 audio_sample_buffer_end = 0;
413         }
414
415         if(audio_sample_buffer_maxsize <= audio_sample_buffer_len + len)
416         {
417                 // Allocate double the needed size
418                 for(int i = 0; i < asset->channels; i++)
419                 {
420                         int16_t *tmp = new int16_t[(audio_sample_buffer_len + len) * 2];
421                         if(!tmp)
422                         {
423                                 fprintf(stderr, _("ERROR: Unable to reallocate memory for "
424                                         "audio_sample_buffer channel %d\n"), i);
425                                 return 1;
426                         }
427                         // Copy everything from audio_sample_buffer into tmp
428                         for(int a = 0, b = audio_sample_buffer_start;
429                                         a < audio_sample_buffer_len;
430                                         a++, b = (b < (audio_sample_buffer_maxsize - 1) ? (b + 1) : 0))
431                         {
432                                 tmp[a] = audio_sample_buffer[i][b];
433                         }
434                         // Free the current buffer, and reassign tmp to audio_sample_buffer[i]
435                         delete[] audio_sample_buffer[i];
436                         audio_sample_buffer[i] = tmp;
437                 }
438                 audio_sample_buffer_start = 0;
439                 audio_sample_buffer_end = audio_sample_buffer_len - 1;
440                 audio_sample_buffer_maxsize = (audio_sample_buffer_len + len) * 2;
441         }
442
443
444         for(int i = 0; i < asset->channels; i++)
445         {
446                 if(len + audio_sample_buffer_end < audio_sample_buffer_maxsize)
447                 {
448                         // copy buffer into audio_sample_buffer, straight out (no loop around)
449                         for(int a = 0; a < len; a++)
450                         {
451                                 audio_sample_buffer[i][audio_sample_buffer_end + a] =
452                                         (buffer[i][a] * 32767);
453                         }
454                         if(i == (asset->channels - 1))
455                                 audio_sample_buffer_end += len;
456                 }
457                 else
458                 {
459                         // Need to loop back to the start of audio_sample_buffer
460                         int copy_size = audio_sample_buffer_maxsize - audio_sample_buffer_end;
461
462                         for(int a = 0; a < copy_size; a++)
463                                 audio_sample_buffer[i][a + audio_sample_buffer_end] =
464                                         (buffer[i][a] * 32767);
465
466                         for(int a = 0; a < len - copy_size; a++)
467                                 audio_sample_buffer[i][a] = (buffer[i][a + copy_size] * 32767);
468
469                         if(i == (asset->channels - 1))
470                                 audio_sample_buffer_end = len - copy_size;
471                 }
472         }
473
474         audio_sample_buffer_len += len;
475
476         return 0;
477 }
478
479 int FileDV::write_samples(double **buffer, int64_t len)
480 {
481         if(audio_samples_copy(buffer, len) != 0)
482         {
483                 eprintf(_("Unable to store sample"));
484                 return 1;
485         }
486         video_position_lock->lock("FileDV::write_samples");
487
488 TRACE("FileDV::write_samples 200")
489         // Get number of frames to be written. Order of operations is important here;
490         // the buffer length must be multiplied by the frame rate first in case the
491         // number of samples in the buffer is less than the sample rate.
492         int nFrames = MIN(video_position - audio_frames_written,
493                                                         audio_sample_buffer_len * asset->frame_rate / asset->sample_rate);
494
495         video_position_lock->unlock();
496
497 TRACE("FileDV::write_samples 220")
498
499         for(int i = 0; i < nFrames; i++)
500         {
501                 stream_lock->lock("FileDV::write_samples 10");
502                 if(fseeko(stream, (off_t) audio_frames_written * output_size, SEEK_SET) != 0)
503                 {
504                         eprintf(_("Unable to set audio write position to %ji\n"), (off_t) audio_frames_written * output_size);
505
506                         stream_lock->unlock();
507                         return 1;
508                 }
509
510                 if(fread(audio_buffer, output_size, 1, stream) != 1)
511                 {
512                         eprintf(_("Unable to read from audio buffer file\n"));
513                         stream_lock->unlock();
514                         return 1;
515                 }
516
517                 stream_lock->unlock();
518
519
520
521 TRACE("FileDV::write_samples 230")
522
523                 int samples = dv_calculate_samples(audio_encoder, asset->sample_rate,
524                                                                 audio_frames_written);
525
526                 if(samples > audio_sample_buffer_maxsize - 1 - audio_sample_buffer_start)
527                 {
528 TRACE("FileDV::write_samples 210")
529                         int16_t *tmp_buf[asset->channels];
530                         for(int a = 0; a < asset->channels; a++)
531                                 tmp_buf[a] = new int16_t[asset->sample_rate];
532
533 TRACE("FileDV::write_samples 240")
534                         int copy_size = audio_sample_buffer_maxsize - audio_sample_buffer_start - 1;
535
536                         for(int a = 0; a < asset->channels; a++)
537                         {
538                                 memcpy(tmp_buf[a], audio_sample_buffer[a] + audio_sample_buffer_start,
539                                         copy_size * sizeof(int16_t));
540                                 memcpy(tmp_buf[a] + copy_size, audio_sample_buffer[a],
541                                         (samples - copy_size) * sizeof(int16_t));
542                         }
543 TRACE("FileDV::write_samples 250")
544                         // Encode the audio into the frame
545                         if(dv_encode_full_audio(audio_encoder, tmp_buf, asset->channels,
546                                 asset->sample_rate, audio_buffer) < 0)
547                         {
548                                 eprintf(_("ERROR: unable to encode audio frame %d\n"), audio_frames_written);
549                         }
550 TRACE("FileDV::write_samples 280")
551
552                         for(int a = 0; a < asset->channels; a++)
553                                 delete[] tmp_buf[a];
554                 }
555                 else
556                 {
557 TRACE("FileDV::write_samples 260")
558                         int16_t **tmp_buf2 = new int16_t*[asset->channels];
559                         for(int a = 0; a < asset->channels; a++)
560                                 tmp_buf2[a] = audio_sample_buffer[a] + audio_sample_buffer_start;
561                         if(dv_encode_full_audio(audio_encoder, tmp_buf2,
562                                 asset->channels, asset->sample_rate, audio_buffer) < 0)
563                         {
564                                 eprintf(_("ERROR: unable to encode audio frame %d\n"), audio_frames_written);
565
566                         }
567                         delete[] tmp_buf2;
568                 }
569
570 TRACE("FileDV::write_samples 270")
571
572                 stream_lock->lock("FileDV::write_samples 20");
573                 if(fseeko(stream, (off_t) audio_frames_written * output_size, SEEK_SET) != 0)
574                 {
575                         eprintf(_("ERROR: Unable to relocate for audio write to %ji\n"), (off_t) audio_frames_written * output_size);
576                         stream_lock->unlock();
577                         return 1;
578                 }
579
580                 if(fwrite(audio_buffer, output_size, 1, stream) != 1)
581                 {
582                         eprintf(_("Unable to write audio to audio buffer\n"));
583                         stream_lock->unlock();
584                         return 1;
585                 }
586
587                 stream_lock->unlock();
588
589                 audio_frames_written++;
590                 audio_sample_buffer_len -= samples;
591                 audio_sample_buffer_start += samples;
592                 if(audio_sample_buffer_start >= audio_sample_buffer_maxsize)
593                         audio_sample_buffer_start -= audio_sample_buffer_maxsize;
594         }
595 TRACE("FileDV::write_samples 290")
596
597 UNTRACE
598
599         return 0;
600 }
601
602 int FileDV::write_frames(VFrame ***frames, int len)
603 {
604         int result = 0;
605
606         if(stream == 0) return 1;
607
608         for(int j = 0; j < len && !result; j++)
609         {
610                 VFrame *temp_frame = frames[0][j];
611
612 //printf("FileDV::write_frames: color_model %i\n", temp_frame->get_color_model());
613                         switch(temp_frame->get_color_model())
614                         {
615                                 case BC_COMPRESSED:
616                                         memcpy(video_buffer, temp_frame->get_data(), output_size);
617                                         break;
618                                 case BC_YUV422:
619 //printf("FileDV::write_frames: 4\n");
620                                         dv_encode_full_frame(encoder, temp_frame->get_rows(),
621                                                 e_dv_color_yuv, video_buffer);
622                                         break;
623                                 case BC_RGB888:
624 //printf("FileDV::write_frames: 5\n");
625                                         dv_encode_full_frame(encoder, temp_frame->get_rows(),
626                                                 e_dv_color_rgb, video_buffer);
627                                         break;
628                                 default:
629                                         unsigned char *data = new unsigned char[asset->height * asset->width * 2];
630                                         unsigned char **cmodel_buf = new unsigned char *[asset->height];
631 //printf("FileDV::write_frames: 6\n");
632                                         unsigned char **row_pointers = temp_frame->get_rows();
633                                         for(int i = 0; i < asset->height; i++)
634                                                 cmodel_buf[i] = data + asset->width * 2 * i;
635
636                                         BC_CModels::transfer(cmodel_buf, row_pointers,
637                                                 cmodel_buf[0], cmodel_buf[1], cmodel_buf[2],
638                                                 row_pointers[0], row_pointers[1], row_pointers[2],
639                                                 0, 0, asset->width, asset->height,
640                                                 0, 0, asset->width, asset->height,
641                                                 temp_frame->get_color_model(), BC_YUV422, 0,
642                                                 asset->width, asset->width);
643
644                                         dv_encode_full_frame(encoder, cmodel_buf,
645                                                 e_dv_color_yuv, video_buffer);
646
647                                         delete[] cmodel_buf;
648                                         delete[] data;
649                                         break;
650                         }
651 //printf("FileDV::write_frames: 7\n");
652
653                 // This is the only thread that modifies video_position,
654                 // so video_position_lock can remain unlocked for reads.
655                 stream_lock->lock("FileDV::write_frames");
656                 if(fseeko(stream, (off_t) video_position * output_size, SEEK_SET) != 0)
657                 {
658                         eprintf(_("Unable to seek file to %ji\n"), (off_t)(video_position * output_size));
659                 }
660                 if(fwrite(video_buffer, output_size, 1, stream) < 1)
661                 {
662                         eprintf(_("Unable to write video data to video buffer"));
663                 }
664                 stream_lock->unlock();
665
666                 video_position_lock->lock();
667                 video_position++;
668                 video_position_lock->unlock();
669         }
670
671         return 0;
672 }
673
674 int FileDV::read_compressed_frame(VFrame *buffer)
675 {
676         int64_t result;
677         if(stream == 0) return 0;
678
679         if (fseeko(stream, (off_t) video_position * output_size, SEEK_SET))
680         {
681                 eprintf(_("Unable to seek file to %ji\n"), (off_t)(video_position * output_size));
682         }
683         result = fread(buffer->get_data(), output_size, 1, stream);
684         video_position++;
685
686         buffer->set_compressed_size(result);
687
688         return result != 0;
689 }
690
691 int FileDV::write_compressed_frame(VFrame *buffer)
692 {
693         int result = 0;
694         if(stream == 0) return 0;
695
696         if (fseeko(stream, (off_t) video_position * output_size, SEEK_SET))
697         {
698                 eprintf(_("Unable to seek file to %ji\n"), (off_t)(video_position * output_size));
699         }
700         result = fwrite(buffer->get_data(), buffer->get_compressed_size(), 1, stream);
701         video_position++;
702         return result != 0;
703 }
704
705 int64_t FileDV::compressed_frame_size()
706 {
707         return output_size;
708 }
709
710 int FileDV::read_samples(double *buffer, int64_t len)
711 {
712         int count = 0;
713         int result = 0;
714         int frame_count = get_audio_frame(audio_position);
715         int offset = get_audio_offset(audio_position);
716
717         stream_lock->lock("FileDV::read_samples");
718         if(stream == 0)
719         {
720                 stream_lock->unlock();
721                 return 1;
722         }
723         stream_lock->unlock();
724
725         // If the sample rate is 32 kHz, and the bitsize is 12, libdv
726         // requires we have space allocated for 4 channels even if
727         // the data only contains two channels.
728
729         // decoder will exist since it is not free'd after open_file
730         int channels = (asset->sample_rate == 32000 && decoder->audio->quantization == 12) ? 4 : 2;
731
732         int16_t **out_buffer = new int16_t*[channels];
733         for(int i = 0; i < channels; i++)
734                 out_buffer[i] = new int16_t[DV_AUDIO_MAX_SAMPLES];
735
736         while(count < len)
737         {
738                 stream_lock->lock();
739
740                 if(fseeko(stream, (off_t) frame_count * output_size, SEEK_SET) != 0)
741                 {
742                         stream_lock->unlock();
743                         result = 1;
744                         break;
745                 }
746
747                 if(fread(audio_buffer, output_size, 1, stream) < 1)
748                 {
749                         stream_lock->unlock();
750                         result = 1;
751                         break;
752                 }
753
754                 stream_lock->unlock();
755
756                 frame_count++;
757
758                 decoder_lock->lock("FileDV::read_samples");
759
760                 if(dv_decode_full_audio(decoder, audio_buffer, out_buffer) < 0)
761                 {
762                         eprintf(_("Error decoding audio frame %d\n"), frame_count - 1);
763                 }
764
765                 int end = dv_get_num_samples(decoder);
766                 decoder_lock->unlock();
767
768                 if(len - count + offset < end)
769                         end = len - count + offset;
770
771                 for(int i = offset; i < end; i++)
772                         buffer[count++] = out_buffer[file->current_channel][i] / 32767.0;
773
774                 offset = 0;
775         }
776
777         for(int i = 0; i < channels; i++)
778                 delete[] out_buffer[i];
779         delete[] out_buffer;
780
781         audio_position += len;
782
783         return result;
784 }
785
786 int FileDV::read_frame(VFrame *frame)
787 {
788         if(stream == 0) return 1;
789         int pitches[3] = {720 * 2, 0, 0};
790
791 TRACE("FileDV::read_frame 1")
792         unsigned char **row_pointers = frame->get_rows();
793
794
795 TRACE("FileDV::read_frame 10")
796
797         // Seek to video position
798         stream_lock->lock("FileDV::read_frame");
799         if(fseeko(stream, (off_t) video_position * output_size, SEEK_SET) < 0)
800         {
801                 eprintf(_("Unable to seek file to %ji"), (off_t)(video_position * output_size));
802                 stream_lock->unlock();
803                 return 1;
804         }
805         fread(video_buffer, output_size, 1, stream);
806         stream_lock->unlock();
807         video_position++;
808
809
810 TRACE("FileDV::read_frame 20")
811
812         switch(frame->get_color_model())
813         {
814                 case BC_COMPRESSED:
815
816 TRACE("FileDV::read_frame 30")
817
818                         frame->allocate_compressed_data(output_size);
819                         frame->set_compressed_size(output_size);
820                         memcpy(frame->get_data(), video_buffer, output_size);
821                         break;
822                 case BC_RGB888:
823
824 TRACE("FileDV::read_frame 40")
825
826                         pitches[0] = 720 * 3;
827                         decoder_lock->lock("FileDV::read_frame 10");
828                         dv_decode_full_frame(decoder, video_buffer, e_dv_color_rgb,
829                                 row_pointers, pitches);
830                         decoder_lock->unlock();
831                         break;
832                 case BC_YUV422:
833 TRACE("FileDV::read_frame 50")
834                         decoder_lock->lock("FileDV::read_frame 20");
835                         dv_decode_full_frame(decoder, video_buffer, e_dv_color_yuv,
836                                 row_pointers, pitches);
837                         decoder_lock->unlock();
838                         break;
839
840                 default:
841                         unsigned char *data = new unsigned char[asset->height * asset->width * 2];
842                         unsigned char **temp_pointers = new unsigned char*[asset->height];
843
844                         for(int i = 0; i < asset->height; i++)
845                                 temp_pointers[i] = data + asset->width * 2 * i;
846
847
848 TRACE("FileDV::read_frame 69")
849
850                         decoder_lock->lock("FileDV::read_frame 30");
851                         dv_decode_full_frame(decoder, video_buffer, e_dv_color_yuv,
852                                 temp_pointers, pitches);
853                         decoder_lock->unlock();
854
855 TRACE("FileDV::read_frame 70")
856
857                         BC_CModels::transfer(row_pointers, temp_pointers,
858                                 row_pointers[0], row_pointers[1], row_pointers[2],
859                                 temp_pointers[0], temp_pointers[1], temp_pointers[2],
860                                 0, 0, asset->width, asset->height,
861                                 0, 0, asset->width, asset->height,
862                                 BC_YUV422, frame->get_color_model(), 0,
863                                 asset->width, asset->width);
864
865                         //for(int i = 0; i < asset->height; i++)
866                         //      delete[] temp_pointers[i];
867                         delete[] temp_pointers;
868                         delete[] data;
869
870
871                         break;
872         }
873
874 TRACE("FileDV::read_frame 80")
875
876 UNTRACE
877
878         return 0;
879 }
880
881 int FileDV::colormodel_supported(int colormodel)
882 {
883         return colormodel;
884 }
885
886 int FileDV::can_copy_from(Edit *edit, int64_t position)
887 {
888         if(edit->asset->format == FILE_RAWDV)
889                 return 1;
890
891         return 0;
892 }
893
894 int FileDV::get_best_colormodel(Asset *asset, int driver)
895 {
896         switch(driver)
897         {
898                 case PLAYBACK_X11:
899                         return BC_RGB888;
900                 case PLAYBACK_X11_XV:
901                         return BC_YUV422;
902                 case PLAYBACK_DV1394:
903                 case PLAYBACK_FIREWIRE:
904                         return BC_COMPRESSED;
905                 case VIDEO4LINUX2:
906                 case VIDEO4LINUX2JPEG:
907                         return BC_YUV422;
908                 case CAPTURE_FIREWIRE:
909                         return BC_COMPRESSED;
910         }
911         return BC_RGB888;
912 }
913
914 int FileDV::get_audio_frame(int64_t pos)
915 {
916         return (double) pos * asset->frame_rate / asset->sample_rate;
917 }
918
919 // Get the sample offset from the frame start reported by get_audio_frame
920 int FileDV::get_audio_offset(int64_t pos)
921 {
922         int frame = get_audio_frame(pos);
923
924         // Samples needed from last frame
925         return  pos - frame * asset->sample_rate / asset->frame_rate;
926 }
927
928
929 DVConfigAudio::DVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
930  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
931         parent_window->get_abs_cursor_x(1),
932         parent_window->get_abs_cursor_y(1),
933         xS(350), yS(250))
934 {
935         this->parent_window = parent_window;
936         this->asset = asset;
937 // *** CONTEXT_HELP ***
938         context_help_set_keyword("Single File Rendering");
939 }
940
941 DVConfigAudio::~DVConfigAudio()
942 {
943
944 }
945
946 void DVConfigAudio::create_objects()
947 {
948         lock_window("DVConfigAudio::create_objects");
949         add_tool(new BC_Title(xS(10), yS(10), _("There are no audio options for this format")));
950         add_subwindow(new BC_OKButton(this));
951         unlock_window();
952 }
953
954 int DVConfigAudio::close_event()
955 {
956         set_done(0);
957         return 1;
958 }
959
960
961 DVConfigVideo::DVConfigVideo(BC_WindowBase *parent_window, Asset *asset)
962  : BC_Window(_(PROGRAM_NAME ": Video Compression"),
963         parent_window->get_abs_cursor_x(1),
964         parent_window->get_abs_cursor_y(1),
965         xS(350), yS(250))
966 {
967         this->parent_window = parent_window;
968         this->asset = asset;
969 // *** CONTEXT_HELP ***
970         context_help_set_keyword("Single File Rendering");
971 }
972
973 DVConfigVideo::~DVConfigVideo()
974 {
975
976 }
977
978 void DVConfigVideo::create_objects()
979 {
980         lock_window("DVConfigVideo::create_objects");
981         add_tool(new BC_Title(xS(10), yS(10), _("There are no video options for this format")));
982         add_subwindow(new BC_OKButton(this));
983         unlock_window();
984 }
985
986 int DVConfigVideo::close_event()
987 {
988         set_done(0);
989         return 1;
990 }
991
992 #endif