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");
44 RecordVideo::~RecordVideo()
50 void RecordVideo::reset_parameters()
54 total_dropped_frames = 0;
56 last_dropped_frames = 0;
62 int RecordVideo::arm_recording()
65 // Resume next file in a series by incrementing existing counters
66 if(record_thread->monitor)
69 buffer_size = mwindow->edl->session->video_write_length;
71 trigger_lock->lock("RecordVideo::arm_recording");
77 void RecordVideo::start_recording()
79 trigger_lock->unlock();
82 int RecordVideo::stop_recording()
84 // Device won't exist if interrupting a cron job
87 // Interrupt IEEE1394 crashes
88 record->vdevice->interrupt_crash();
90 // Interrupt video4linux crashes
91 if(record->vdevice->get_failed())
103 int RecordVideo::cleanup_recording()
105 if(!record_thread->monitor)
107 //printf("RecordVideo::cleanup_recording 1\n");
111 //printf("RecordVideo::cleanup_recording 2\n");
115 delete [] frame_ptr[0];
117 delete capture_frame;
122 void RecordVideo::get_capture_frame()
124 if(record->fixed_compression)
126 capture_frame = new VFrame;
130 capture_frame = new VFrame(0,
131 record->default_asset->width,
132 record->default_asset->height,
133 record->vdevice->get_best_colormodel(record->default_asset));
134 //printf("RecordVideo::get_capture_frame %d %d\n", capture_frame->get_w(), capture_frame->get_h());
136 frame_ptr = new VFrame**[1];
137 frame_ptr[0] = new VFrame*[1];
138 frame_ptr[0][0] = capture_frame;
142 void RecordVideo::run()
147 // Thread out the I/O
148 if(!record_thread->monitor)
150 record_start = record->file->get_video_position(record->default_asset->frame_rate);
151 frame_ptr = record->file->get_video_buffer();
158 // Number of frames for user to know about.
159 gui->total_dropped_frames = 0;
160 gui->update_dropped_frames(0);
164 trigger_lock->lock("RecordVideo::run");
165 trigger_lock->unlock();
170 // Synchronize with audio or timer
172 next_sample = (int64_t)((float)record->get_current_batch()->session_frames /
173 record->default_asset->frame_rate *
174 record->default_asset->sample_rate);
175 current_sample = record->sync_position();
178 if(current_sample < next_sample && current_sample > 0)
181 delay = (int64_t)((float)(next_sample - current_sample) /
182 record->default_asset->sample_rate *
184 // Sanity check and delay.
185 // In 2.6.7 this doesn't work. For some reason, probably buffer overflowing,
186 // it causes the driver to hang up momentarily so we try to only delay
187 // when really really far ahead.
188 if(delay < 2000 && delay > 0) delayer.delay(delay);
189 gui->update_dropped_frames(0);
190 last_dropped_frames = 0;
193 if(current_sample > 0 && !record_thread->monitor)
196 dropped_frames = (int64_t)((float)(current_sample - next_sample) /
197 record->default_asset->sample_rate *
198 record->default_asset->frame_rate);
199 if(dropped_frames != last_dropped_frames)
201 gui->update_dropped_frames(dropped_frames);
202 last_dropped_frames = dropped_frames;
204 last_dropped_frames = dropped_frames;
212 // Grab frame for recording
213 if(!record_thread->monitor)
215 capture_frame = frame_ptr[0][buffer_position];
216 record->vdevice->set_field_order(record->reverse_interlace);
218 record->get_current_batch()->current_frame++;
219 record->get_current_batch()->total_frames =
220 MAX(record->get_current_batch()->current_frame, record->get_current_batch()->total_frames);
221 record->get_current_batch()->session_frames++;
222 if(!grab_result) buffer_position++;
224 // Update the position indicator
225 gui->update_position(record->current_display_position());
228 // Grab frame for monitoring
229 if(record->monitor_video)
231 record->vdevice->set_field_order(record->reverse_interlace);
232 record->get_current_batch()->session_frames++;
237 // Brief pause to keep CPU from burning up
243 // Monitor the frame if monitoring
244 // printf("RecordVideo::run %p %d %d %d\n",
245 // capture_frame->get_data(),
246 // record->monitor_video,
249 if(capture_frame->get_data() &&
250 record->monitor_video &&
254 record->record_monitor->update(capture_frame);
257 // Duplicate a frame if behind
258 if(!record_thread->monitor &&
259 record->fill_frames &&
263 VFrame *last_frame = capture_frame;
265 if(buffer_position >= buffer_size) write_buffer(0);
267 capture_frame = frame_ptr[0][buffer_position];
268 capture_frame->copy_from(last_frame);
269 record->get_current_batch()->current_frame++;
270 record->get_current_batch()->total_frames =
271 MAX(record->get_current_batch()->current_frame, record->get_current_batch()->total_frames);
272 record->get_current_batch()->session_frames++;
276 // Compress a batch of frames or write the second frame if filling
277 if(!record_thread->monitor && buffer_position >= buffer_size)
282 if(!record_thread->monitor &&
286 // Handle recording contexts
287 if(record_thread->context == CONTEXT_SINGLEFRAME)
292 // Handle recording modes delegated to the thread
293 switch(record->get_current_batch()->record_mode)
296 if(record->current_display_position() > *record->current_duration())
300 if(record->current_display_position() > *record->current_duration())
303 case RECORD_SCENETOSCENE:
314 //TRACE("RecordVideo::run 1");
315 // Update dependant threads
316 if(record->default_asset->audio_data)
318 record_thread->record_audio->batch_done = 1;
319 // Interrupt driver for IEEE1394
320 record_thread->record_audio->stop_recording();
323 //TRACE("RecordVideo::run 2");
327 if(!record_thread->monitor)
329 ErrorBox error_box(PROGRAM_NAME ": Error",
330 mwindow->gui->get_abs_cursor_x(1),
331 mwindow->gui->get_abs_cursor_y(1));
332 error_box.create_objects(_("No space left on disk."));
333 error_box.run_window();
339 //TRACE("RecordVideo::run 100");
342 void RecordVideo::read_buffer()
344 grab_result = record->vdevice->read_buffer(capture_frame);
347 // Get field offset for monitor
348 if(!strncmp(record->default_asset->vcodec, QUICKTIME_MJPA, 4) &&
349 record->vdevice->is_compressed(0, 1))
351 unsigned char *data = capture_frame->get_data();
352 int64_t size = capture_frame->get_compressed_size();
353 int64_t allocation = capture_frame->get_compressed_allocated();
357 int64_t field2_offset = mjpeg_get_field2(data, size);
358 capture_frame->set_compressed_size(size);
359 capture_frame->set_field2_offset(field2_offset);
364 void RecordVideo::write_buffer(int skip_new)
366 write_result = record->file->write_video_buffer(buffer_position);
368 if(!skip_new && !write_result)
369 frame_ptr = record->file->get_video_buffer();
372 void RecordVideo::rewind_file()
375 record->file->stop_video_thread();
376 record->file->set_video_position(0, record->default_asset->frame_rate);
377 record->file->start_video_thread(buffer_size,
378 record->vdevice->get_best_colormodel(record->default_asset),
380 record->vdevice->is_compressed(1, 0));
381 frame_ptr = record->file->get_video_buffer();
382 record->get_current_batch()->current_frame = 0;
383 record->get_current_batch()->current_sample = 0;
384 record->get_current_batch()->session_frames = 0;
385 record->get_current_batch()->session_samples = 0;
386 gui->update_position(0);
389 int RecordVideo::unhang_thread()
391 printf("RecordVideo::unhang_thread\n");