7 #include "edlsession.h"
10 #include "filethread.h"
14 #include "mwindowgui.h"
15 #include "preferences.h"
16 #include "quicktime.h"
18 #include "recordaudio.h"
19 #include "recordgui.h"
20 #include "recordthread.h"
21 #include "recordvideo.h"
22 #include "recordmonitor.h"
25 #include "videodevice.h"
30 RecordVideo::RecordVideo(MWindow *mwindow,
32 RecordThread *record_thread)
36 this->mwindow = mwindow;
37 this->record = record;
38 this->record_thread = record_thread;
39 this->gui = record->record_gui;
40 unhang_lock = new Mutex("RecordVideo::unhang_lock");
41 trigger_lock = new Condition(1, "RecordVideo::trigger_lock");
46 RecordVideo::~RecordVideo()
50 // These objects are shared with the file if recording.
51 if(record_thread->monitor)
55 if(frame_ptr[0]) delete [] frame_ptr[0];
62 void RecordVideo::reset_parameters()
66 total_dropped_frames = 0;
68 last_dropped_frames = 0;
74 int RecordVideo::arm_recording()
77 // Resume next file in a series by incrementing existing counters
78 if(record_thread->monitor)
81 buffer_size = mwindow->edl->session->video_write_length;
83 trigger_lock->lock("RecordVideo::arm_recording");
89 void RecordVideo::start_recording()
91 trigger_lock->unlock();
94 int RecordVideo::stop_recording()
96 // Device won't exist if interrupting a cron job
99 // Interrupt IEEE1394 crashes
100 record->vdevice->interrupt_crash();
102 // Interrupt video4linux crashes
103 if(record->vdevice->get_failed())
111 // Joined in RecordThread
116 int RecordVideo::cleanup_recording()
118 if(!record_thread->monitor)
126 // RecordMonitorThread still needs capture_frame if uncompressed.
127 // delete [] frame_ptr[0];
128 // delete [] frame_ptr;
129 // delete capture_frame;
134 void RecordVideo::get_capture_frame()
138 if(record->fixed_compression)
140 capture_frame = new VFrame;
144 capture_frame = new VFrame(0,
145 record->default_asset->width,
146 record->default_asset->height,
147 record->vdevice->get_best_colormodel(record->default_asset));
148 //printf("RecordVideo::get_capture_frame %d %d\n", capture_frame->get_w(), capture_frame->get_h());
150 frame_ptr = new VFrame**[1];
151 frame_ptr[0] = new VFrame*[1];
152 frame_ptr[0][0] = capture_frame;
157 void RecordVideo::run()
162 // Thread out the I/O
163 if(!record_thread->monitor)
165 record_start = record->file->get_video_position(record->default_asset->frame_rate);
166 frame_ptr = record->file->get_video_buffer();
173 // Number of frames for user to know about.
174 gui->total_dropped_frames = 0;
175 gui->update_dropped_frames(0);
179 trigger_lock->lock("RecordVideo::run");
180 trigger_lock->unlock();
185 // Synchronize with audio or timer
187 next_sample = (int64_t)((float)record->get_current_batch()->session_frames /
188 record->default_asset->frame_rate *
189 record->default_asset->sample_rate);
190 current_sample = record->sync_position();
193 if(current_sample < next_sample && current_sample > 0)
196 delay = (int64_t)((float)(next_sample - current_sample) /
197 record->default_asset->sample_rate *
199 // Sanity check and delay.
200 // In 2.6.7 this doesn't work. For some reason, probably buffer overflowing,
201 // it causes the driver to hang up momentarily so we try to only delay
202 // when really really far ahead.
203 if(delay < 2000 && delay > 0)
205 delayer.delay(delay);
207 gui->update_dropped_frames(0);
208 last_dropped_frames = 0;
211 if(current_sample > 0 && !record_thread->monitor)
214 dropped_frames = (int64_t)((float)(current_sample - next_sample) /
215 record->default_asset->sample_rate *
216 record->default_asset->frame_rate);
217 if(dropped_frames != last_dropped_frames)
219 gui->update_dropped_frames(dropped_frames);
220 last_dropped_frames = dropped_frames;
222 last_dropped_frames = dropped_frames;
230 // Grab frame for recording
231 if(!record_thread->monitor)
233 capture_frame = frame_ptr[0][buffer_position];
234 record->vdevice->set_field_order(record->reverse_interlace);
236 record->get_current_batch()->current_frame++;
237 record->get_current_batch()->total_frames =
238 MAX(record->get_current_batch()->current_frame, record->get_current_batch()->total_frames);
239 record->get_current_batch()->session_frames++;
240 if(!grab_result) buffer_position++;
242 // Update the position indicator
243 gui->update_position(record->current_display_position());
246 // Grab frame for monitoring
247 if(record->monitor_video)
249 record->vdevice->set_field_order(record->reverse_interlace);
250 record->get_current_batch()->session_frames++;
255 // Brief pause to keep CPU from burning up
261 // Monitor the frame if monitoring
262 // printf("RecordVideo::run %p %d %d %d\n",
263 // capture_frame->get_data(),
264 // record->monitor_video,
267 if(capture_frame->get_data() &&
268 record->monitor_video &&
272 record->record_monitor->update(capture_frame);
275 // Duplicate a frame if behind
276 if(!record_thread->monitor &&
277 record->fill_frames &&
281 VFrame *last_frame = capture_frame;
283 if(buffer_position >= buffer_size) write_buffer(0);
285 capture_frame = frame_ptr[0][buffer_position];
286 capture_frame->copy_from(last_frame);
287 record->get_current_batch()->current_frame++;
288 record->get_current_batch()->total_frames =
289 MAX(record->get_current_batch()->current_frame, record->get_current_batch()->total_frames);
290 record->get_current_batch()->session_frames++;
294 // Compress a batch of frames or write the second frame if filling
295 if(!record_thread->monitor && buffer_position >= buffer_size)
300 if(!record_thread->monitor &&
304 // Handle recording contexts
305 if(record_thread->context == CONTEXT_SINGLEFRAME)
310 // Handle recording modes delegated to the thread
311 switch(record->get_current_batch()->record_mode)
314 if(record->current_display_position() > *record->current_duration())
318 if(record->current_display_position() > *record->current_duration())
321 case RECORD_SCENETOSCENE:
332 //TRACE("RecordVideo::run 1");
333 // Update dependant threads
334 if(record->default_asset->audio_data)
336 record_thread->record_audio->batch_done = 1;
337 // Interrupt driver for IEEE1394
338 record_thread->record_audio->stop_recording();
341 //TRACE("RecordVideo::run 2");
345 if(!record_thread->monitor)
347 ErrorBox error_box(PROGRAM_NAME ": Error",
348 mwindow->gui->get_abs_cursor_x(1),
349 mwindow->gui->get_abs_cursor_y(1));
350 error_box.create_objects(_("No space left on disk."));
351 error_box.run_window();
360 void RecordVideo::read_buffer()
362 grab_result = record->vdevice->read_buffer(capture_frame);
365 // Get field offset for monitor
366 if(!strncmp(record->default_asset->vcodec, QUICKTIME_MJPA, 4) &&
367 record->vdevice->is_compressed(0, 1))
369 unsigned char *data = capture_frame->get_data();
370 int64_t size = capture_frame->get_compressed_size();
371 int64_t allocation = capture_frame->get_compressed_allocated();
375 int64_t field2_offset = mjpeg_get_field2(data, size);
376 capture_frame->set_compressed_size(size);
377 capture_frame->set_field2_offset(field2_offset);
382 void RecordVideo::write_buffer(int skip_new)
384 write_result = record->file->write_video_buffer(buffer_position);
386 if(!skip_new && !write_result)
387 frame_ptr = record->file->get_video_buffer();
390 void RecordVideo::rewind_file()
393 record->file->stop_video_thread();
394 record->file->set_video_position(0, record->default_asset->frame_rate);
395 record->file->start_video_thread(buffer_size,
396 record->vdevice->get_best_colormodel(record->default_asset),
398 record->vdevice->is_compressed(1, 0));
399 frame_ptr = record->file->get_video_buffer();
400 record->get_current_batch()->current_frame = 0;
401 record->get_current_batch()->current_sample = 0;
402 record->get_current_batch()->session_frames = 0;
403 record->get_current_batch()->session_samples = 0;
404 gui->update_position(0);
407 int RecordVideo::unhang_thread()
409 printf("RecordVideo::unhang_thread\n");
416 // c-file-style: "linux"