+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "asset.h"
-#include "batch.h"
-#include "bcsignals.h"
-#include "clip.h"
-#include "condition.h"
-#include "edl.h"
-#include "edlsession.h"
-#include "errorbox.h"
-#include "file.h"
-#include "filethread.h"
-#include "language.h"
-#include "libmjpeg.h"
-#include "mutex.h"
-#include "mwindow.h"
-#include "mwindowgui.h"
-#include "preferences.h"
-#include "record.h"
-#include "recordaudio.h"
-#include "recordgui.h"
-#include "recordvideo.h"
-#include "recordmonitor.h"
-#include "units.h"
-#include "vframe.h"
-#include "videodevice.h"
-
-#include <unistd.h>
-
-
-RecordVideo::RecordVideo(MWindow *mwindow, Record *record)
- : Thread(1, 0, 0)
-{
- this->mwindow = mwindow;
- this->record = record;
- this->gui = record->record_gui;
- trigger_lock = new Condition(0, "RecordVideo::trigger_lock");
- pause_record_lock = new Condition(0, "RecordVideo::pause_record_lock");
- record_paused_lock = new Condition(0, "RecordVideo::record_paused_lock");
- frame_ptr = 0;
- buffer_frame = 0;
- reset_parameters();
- done = -1;
-}
-
-RecordVideo::~RecordVideo()
-{
- stop_recording();
- delete_buffer();
- delete trigger_lock;
- delete pause_record_lock;
- delete record_paused_lock;
-}
-
-void RecordVideo::reset_parameters()
-{
- write_result = 0;
- writing_file = 0;
- grab_result = 0;
- buffer_frames = mwindow->edl->session->video_write_length;
- buffer_position = 0;
- recording_paused = 0;
- record_start = 0;
- trigger_lock->reset();
- pause_record_lock->reset();
- record_paused_lock->reset();
-}
-
-void RecordVideo::arm_recording()
-{
- reset_parameters();
- done = 0;
- Thread::start();
-}
-
-void RecordVideo::start_recording()
-{
- trigger_lock->unlock();
-}
-
-void RecordVideo::stop_recording()
-{
- if( done ) return;
-// Device won't exist if interrupting a cron job
- done = 1;
- if( record->vdevice ) {
-// Interrupt IEEE1394 crashes
- record->vdevice->interrupt_crash();
-// Interrupt video4linux crashes
- if( record->vdevice->get_failed() )
- Thread::cancel();
- }
- Thread::join();
-// Joined in RecordThread
-}
-
-
-VFrame *RecordVideo::get_buffer()
-{
- VFrame *result = 0;
- record->file_lock->lock();
- writing_file = record->writing_file > 0 && record->do_video ? 1 : 0;
- if( writing_file ) {
- if( !frame_ptr ) {
- frame_ptr = record->file->get_video_buffer();
- buffer_position = 0;
- }
- result = frame_ptr[0][buffer_position];
-
- }
- record->file_lock->unlock();
- if( !result ) {
- if( !buffer_frame ) {
- if( !record->fixed_compression ) {
- Asset *asset = record->default_asset;
- int w = asset->width, h = asset->height;
- int cmodel = record->vdevice->get_best_colormodel(asset);
- buffer_frame = new VFrame(w, h, cmodel);
- }
- else
- buffer_frame = new VFrame;
- }
- buffer_position = 0;
- result = buffer_frame;
- }
- return result;
-}
-
-void RecordVideo::delete_buffer()
-{
- RecordMonitorThread *thr = !record->record_monitor ?
- 0 : record->record_monitor->thread;
- if( thr && thr->running() ) thr->lock_input();
- frame_ptr = 0;
- if( buffer_frame ) {
- delete buffer_frame;
- buffer_frame = 0;
- }
- if( thr && thr->running() ) thr->unlock_input();
-}
-
-void RecordVideo::config_update()
-{
- VideoDevice *vdevice = record->vdevice;
- vdevice->config_update();
- int width = vdevice->get_iwidth();
- int height = vdevice->get_iheight();
- double frame_rate = vdevice->get_irate();
- float awidth, aheight;
- MWindow::create_aspect_ratio(awidth, aheight, width, height);
- EDLSession *session = record->edl->session;
- SESSION->aspect_w = session->aspect_w = awidth;
- SESSION->aspect_h = session->aspect_h = aheight;
- SESSION->output_w = session->output_w = width;
- SESSION->output_h = session->output_h = height;
- Asset *rf_asset = SESSION->recording_format;
- Asset *df_asset = record->default_asset;
- rf_asset->width = df_asset->width = width;
- rf_asset->height = df_asset->height = height;
- rf_asset->frame_rate = df_asset->frame_rate = frame_rate;
-}
-
-void RecordVideo::run()
-{
-// Number of frames for user to know about.
- gui->reset_video();
-
-// Wait for trigger
- trigger_lock->lock("RecordVideo::run");
-
- while( !done && !write_result ) {
- if( recording_paused ) {
- pause_record_lock->unlock();
- record_paused_lock->lock();
- }
- if( done ) break;
- VideoDevice *vdevice = record->vdevice;
- VFrame *capture_frame = get_buffer();
- vdevice->set_field_order(record->reverse_interlace);
-// Capture a frame
- grab_result = read_buffer(capture_frame);
- if( done ) break;
- if( vdevice->config_updated() ) {
- flush_buffer();
- delete_buffer();
- config_update();
- gui->reset_video();
- record->record_monitor->reconfig();
- continue;
- }
- if( grab_result ) {
- Timer::delay(250);
- continue;
- }
- decompress_buffer(capture_frame);
- record->resync();
- write_buffer();
- if( record->monitor_video && capture_frame->get_data() )
- if( !writing_file || !record->is_behind() )
- record->record_monitor->update(capture_frame);
- if( writing_file && record->fill_underrun_frames ) {
- VFrame *last_frame = capture_frame;
- int fill = record->dropped;
- while( --fill >= 0 ) {
- capture_frame = get_buffer();
- capture_frame->copy_from(last_frame);
- last_frame = capture_frame;
- write_buffer();
- }
- }
- else
- record->written_frames += record->dropped;
- if( record->single_frame ) {
- record->single_frame = 0;
- record->stop_writing_file();
- }
- if( done ) break;
- if( !done ) done = write_result;
- if( done ) break;
- record->check_batch_complete();
- }
-
-SET_TRACE
- flush_buffer();
- delete_buffer();
-SET_TRACE
-//TRACE("RecordVideo::run 2");
- if( write_result ) {
- ErrorBox error_box(_(PROGRAM_NAME ": Error"),
- mwindow->gui->get_abs_cursor_x(1),
- mwindow->gui->get_abs_cursor_y(1));
- error_box.create_objects(_("No space left on disk."));
- error_box.run_window();
- }
-SET_TRACE
-}
-
-int RecordVideo::read_buffer(VFrame *frame)
-{
- return record->vdevice->read_buffer(frame);
-}
-
-void RecordVideo::decompress_buffer(VFrame *frame)
-{
- if( !strcmp(record->default_asset->vcodec, CODEC_TAG_MJPEG) &&
- record->vdevice->is_compressed(0, 1)) {
- unsigned char *data = frame->get_data();
- int64_t size = frame->get_compressed_size();
- //int64_t allocation = frame->get_compressed_allocated();
- if( data ) {
- int64_t field2_offset = mjpeg_get_field2(data, size);
- frame->set_compressed_size(size);
- frame->set_field2_offset(field2_offset);
- }
- }
-}
-
-int RecordVideo::flush_buffer()
-{
- record->file_lock->lock();
- if( writing_file && frame_ptr ) {
- int result = record->file->write_video_buffer(buffer_position);
- if( result ) write_result = 1;
- frame_ptr = 0;
- }
- record->file_lock->unlock();
- buffer_position = 0;
- return write_result;
-}
-
-int RecordVideo::write_buffer()
-{
- ++record->written_frames;
- if( ++buffer_position >= buffer_frames )
- flush_buffer();
-// HACK
-write_result = 0;
- return write_result;
-}
-
-void RecordVideo::pause_recording()
-{
- recording_paused = 1;
- pause_record_lock->lock();
-}
-
-void RecordVideo::resume_recording()
-{
- recording_paused = 0;
- record_paused_lock->unlock();
-}
-