5 #include "filethread.h"
8 #include "videodevice.inc"
14 FileThreadFrame::FileThreadFrame()
20 FileThreadFrame::~FileThreadFrame()
22 if(frame) delete frame;
27 FileThread::FileThread(File *file, int do_audio, int do_video)
36 FileThread::~FileThread()
43 void FileThread::reset()
63 bzero(read_frames, sizeof(FileThreadFrame*) * MAX_READ_FRAMES);
67 void FileThread::create_objects(File *file,
72 this->do_audio = do_audio;
73 this->do_video = do_video;
74 file_lock = new Mutex("FileThread::file_lock");
75 read_wait_lock = new Condition(0, "FileThread::read_wait_lock");
76 user_wait_lock = new Condition(0, "FileThread::user_wait_lock");
77 frame_lock = new Mutex("FileThread::frame_lock");
78 for(int i = 0; i < MAX_READ_FRAMES; i++)
79 read_frames[i] = new FileThreadFrame;
83 void FileThread::delete_objects()
87 for(int i = 0; i < ring_buffers; i++)
89 delete output_lock[i];
91 delete [] output_lock;
96 for(int i = 0; i < ring_buffers; i++)
100 delete [] input_lock;
105 delete [] last_buffer;
108 delete [] output_size;
113 delete read_wait_lock;
114 delete user_wait_lock;
120 void FileThread::run()
127 while(!done && !disable_read)
129 frame_lock->lock("FileThread::run 1");
130 int local_total_frames = total_frames;
131 frame_lock->unlock();
133 if(local_total_frames >= MAX_READ_FRAMES)
135 read_wait_lock->lock("FileThread::run");
139 if(done || disable_read) break;
141 // Make local copes of the locked parameters
142 FileThreadFrame *local_frame = 0;
143 int64_t local_position = 0;
146 frame_lock->lock("FileThread::run 2");
147 // Get position of next frame to read
149 local_position = read_frames[total_frames - 1]->position + 1;
151 local_position = start_position;
152 //printf("FileThread::run 1 %d %lld\n", total_frames, local_position);
154 // Get first available frame
155 local_total_frames = total_frames;
156 local_frame = read_frames[local_total_frames];
158 frame_lock->unlock();
163 file->set_video_position(local_position, -1, 1);
164 file->set_layer(local_layer, 1);
165 int supported_colormodel =
166 file->get_best_colormodel(PLAYBACK_ASYNCHRONOUS);
170 if(local_frame->frame &&
171 !local_frame->frame->params_match(file->asset->width,
173 supported_colormodel))
175 delete local_frame->frame;
176 local_frame->frame = 0;
179 if(!local_frame->frame)
181 local_frame->frame = new VFrame(0,
184 supported_colormodel);
188 //printf("FileThread::run %lld\n", local_position);
189 file->read_frame(local_frame->frame, 1);
190 local_frame->position = local_position;
191 local_frame->layer = local_layer;
193 // Put frame in last position but since the last position now may be
194 // lower than it was when we got the frame, swap the current
195 // last position with the previous last position.
196 frame_lock->lock("FileThread::run 3");
197 FileThreadFrame *old_frame = read_frames[total_frames];
198 read_frames[local_total_frames] = old_frame;
199 read_frames[total_frames++] = local_frame;
200 frame_lock->unlock();
203 user_wait_lock->unlock();
211 output_lock[local_buffer]->lock("FileThread::run 1");
217 if(!last_buffer[local_buffer])
219 if(output_size[local_buffer])
221 file_lock->lock("FileThread::run 2");
224 result = file->write_samples(audio_buffer[local_buffer],
225 output_size[local_buffer]);
233 for(j = 0; j < file->asset->layers && !result; j++)
234 for(i = 0; i < output_size[local_buffer] && !result; i++)
235 result = file->write_compressed_frame(video_buffer[local_buffer][j][i]);
239 result = file->write_frames(video_buffer[local_buffer],
240 output_size[local_buffer]);
245 return_value = result;
250 output_size[local_buffer] = 0;
255 input_lock[local_buffer]->unlock();
257 if(local_buffer >= ring_buffers) local_buffer = 0;
264 int FileThread::stop_writing()
268 int i, buffer, layer, frame;
271 input_lock[current_buffer]->lock("FileThread::stop_writing 1");
273 last_buffer[current_buffer] = 1;
275 for(i = 0; i < ring_buffers; i++)
276 output_lock[i]->unlock();
280 // wait for thread to finish
284 file_lock->lock("FileThread::stop_writing 2");
287 for(buffer = 0; buffer < ring_buffers; buffer++)
289 for(i = 0; i < file->asset->channels; i++)
290 delete [] audio_buffer[buffer][i];
291 delete [] audio_buffer[buffer];
293 delete [] audio_buffer;
297 // printf("FileThread::stop_writing %d %d %d %d\n",
300 // file->asset->layers,
304 for(buffer = 0; buffer < ring_buffers; buffer++)
306 for(layer = 0; layer < file->asset->layers; layer++)
308 for(frame = 0; frame < buffer_size; frame++)
310 delete video_buffer[buffer][layer][frame];
312 delete [] video_buffer[buffer][layer];
314 delete [] video_buffer[buffer];
316 delete [] video_buffer;
325 int FileThread::start_writing(long buffer_size,
331 int buffer, layer, frame;
332 long bytes_per_frame;
334 this->ring_buffers = ring_buffers;
335 this->buffer_size = buffer_size;
336 this->color_model = color_model;
337 this->compressed = compressed;
338 this->current_buffer = ring_buffers - 1;
342 file_lock->lock("FileThread::start_writing 1");
347 // Buffer is swapped before first get
348 last_buffer = new int[ring_buffers];
349 output_size = new long[ring_buffers];
352 output_lock = new Condition*[ring_buffers];
353 input_lock = new Condition*[ring_buffers];
354 for(int i = 0; i < ring_buffers; i++)
356 output_lock[i] = new Condition(0, "FileThread::output_lock");
357 input_lock[i] = new Condition(1, "FileThread::input_lock");
366 audio_buffer = new double**[ring_buffers];
367 for(buffer = 0; buffer < ring_buffers; buffer++)
369 audio_buffer[buffer] = new double*[file->asset->channels];
371 for(int channel = 0; channel < file->asset->channels; channel++)
373 audio_buffer[buffer][channel] = new double[buffer_size];
380 this->color_model = color_model;
381 bytes_per_frame = VFrame::calculate_data_size(file->asset->width,
386 video_buffer = new VFrame***[ring_buffers];
387 // printf("FileThread::start_writing 1 %d %d %d %p\n",
389 // file->asset->layers,
392 for(buffer = 0; buffer < ring_buffers; buffer++)
394 video_buffer[buffer] = new VFrame**[file->asset->layers];
395 for(layer = 0; layer < file->asset->layers; layer++)
397 video_buffer[buffer][layer] = new VFrame*[buffer_size];
398 for(frame = 0; frame < buffer_size; frame++)
401 video_buffer[buffer][layer][frame] = new VFrame;
404 video_buffer[buffer][layer][frame] =
409 // printf("FileThread::start_writing 4 %d %d %d %p\n",
413 // video_buffer[buffer][layer]);
421 for(int i = 0; i < ring_buffers; i++)
432 int FileThread::start_reading()
443 int FileThread::stop_reading()
445 if(is_reading && Thread::running())
448 read_wait_lock->unlock();
454 int FileThread::set_video_position(int64_t position)
456 // If the new position can't be added to the buffer without restarting,
458 if((position < this->start_position ||
459 position >= this->start_position + MAX_READ_FRAMES) &&
463 read_wait_lock->unlock();
467 this->start_position = position;
470 // If a sequential read, enable reading
471 if(this->start_position + 1 == position && disable_read)
473 this->start_position = position;
480 this->start_position = position;
483 this->read_position = position;
487 int FileThread::set_layer(int layer)
489 if(layer != this->layer)
492 read_wait_lock->unlock();
500 int FileThread::read_frame(VFrame *frame)
502 FileThreadFrame *local_frame = 0;
506 //printf("FileThread::read_frame 1\n");
508 // Search thread for frame
509 while(!got_it && !disable_read)
511 frame_lock->lock("FileThread::read_frame 1");
512 // printf("FileThread::read_frame: 1 read_position=%lld ", read_position);
513 // for(int i = 0; i < total_frames; i++)
514 // printf("%lld ", read_frames[i]->position);
516 for(int i = 0; i < total_frames; i++)
518 local_frame = read_frames[i];
519 if(local_frame->position == read_position &&
520 local_frame->layer == layer &&
521 local_frame->frame &&
522 local_frame->frame->equal_stacks(frame))
526 //printf("FileThread::read_frame 1 %lld\n", local_frame->position);
530 frame_lock->unlock();
532 // Not decoded yet but thread active
533 if(!got_it && !disable_read)
535 user_wait_lock->lock("FileThread::read_frame");
538 //printf("FileThread::read_frame 2\n");
543 cmodel_transfer(frame->get_rows(),
544 local_frame->frame->get_rows(),
548 local_frame->frame->get_y(),
549 local_frame->frame->get_u(),
550 local_frame->frame->get_v(),
553 local_frame->frame->get_w(),
554 local_frame->frame->get_h(),
559 local_frame->frame->get_color_model(),
560 frame->get_color_model(),
562 local_frame->frame->get_w(),
564 // Can't copy stacks because the stack is needed by the plugin requestor.
565 frame->copy_params(local_frame->frame);
567 // Recycle all frames before current one but not including current one.
568 // This handles redrawing of a single frame but because FileThread has no
569 // notion of a still frame, it has to call read_frame for those.
570 frame_lock->lock("FileThread::read_frame 1");
571 FileThreadFrame *new_table[MAX_READ_FRAMES];
573 for(int j = number; j < total_frames; j++, k++)
575 new_table[k] = read_frames[j];
577 for(int j = 0; j < number; j++, k++)
579 new_table[k] = read_frames[j];
581 memcpy(read_frames, new_table, sizeof(FileThreadFrame*) * total_frames);
582 total_frames -= number;
584 start_position = read_position;
586 frame_lock->unlock();
587 read_wait_lock->unlock();
592 // printf("FileThread::read_frame 1 color_model=%d disable_read=%d\n",
593 // frame->get_color_model(),
595 // Use traditional read function
596 file->set_video_position(read_position, -1, 1);
597 file->set_layer(layer, 1);
599 return file->read_frame(frame, 1);
601 //printf("FileThread::read_frame 100\n");
604 int64_t FileThread::get_memory_usage()
606 frame_lock->lock("FileThread::get_memory_usage");
608 for(int i = 0; i < MAX_READ_FRAMES; i++)
609 if(read_frames[i] && read_frames[i]->frame)
610 result += read_frames[i]->frame->get_data_size();
611 frame_lock->unlock();
616 double** FileThread::get_audio_buffer()
620 input_lock[current_buffer]->lock("FileThread::get_audio_buffer");
621 return audio_buffer[current_buffer];
624 VFrame*** FileThread::get_video_buffer()
628 input_lock[current_buffer]->lock("FileThread::get_video_buffer");
629 return video_buffer[current_buffer];
632 int FileThread::write_buffer(long size)
634 output_size[current_buffer] = size;
636 // unlock the output lock
637 output_lock[current_buffer]->unlock();
642 int FileThread::swap_buffer()
645 if(current_buffer >= ring_buffers) current_buffer = 0;