summaryrefslogtreecommitdiff
path: root/src/lib/writer.h
blob: beb16c7b9107da1972bcbd5f92a2dc07d3b1b701 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
    Copyright (C) 2012 Carl Hetherington <cth@carlh.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., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include <list>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include "exceptions.h"

class Film;
class EncodedData;
class AudioBuffers;

namespace libdcp {
	class MonoPictureAsset;
	class MonoPictureAssetWriter;
	class SoundAsset;
	class SoundAssetWriter;
}

struct QueueItem
{
public:
	enum Type {
		/** a normal frame with some JPEG200 data */
		FULL,
		/** a frame whose data already exists in the MXF,
		    and we fake-write it; i.e. we update the writer's
		    state but we use the data that is already on disk.
		*/
		FAKE,
		/** this is a repeat of the last frame to be written */
		REPEAT
	} type;

	/** encoded data for FULL */
	boost::shared_ptr<const EncodedData> encoded;
	/** size of data for FAKE */
	int size;
	/** frame index */
	int frame;
};

bool operator< (QueueItem const & a, QueueItem const & b);
bool operator== (QueueItem const & a, QueueItem const & b);

class Writer : public ExceptionStore
{
public:
	Writer (boost::shared_ptr<Film>);

	bool can_fake_write (int) const;
	
	void write (boost::shared_ptr<const EncodedData>, int);
	void fake_write (int);
	void write (boost::shared_ptr<const AudioBuffers>);
	void repeat (int f);
	void finish ();

private:

	void thread ();
	void check_existing_picture_mxf ();

	/** our Film */
	boost::shared_ptr<Film> _film;
	/** the first frame index that does not already exist in our MXF */
	int _first_nonexistant_frame;

	/** our thread, or 0 */
	boost::thread* _thread;
	/** true if our thread should finish */
	bool _finish;
	/** queue of things to write to disk */
	std::list<QueueItem> _queue;
	/** number of FULL frames whose JPEG200 data is currently held in RAM */
	int _queued_full_in_memory;
	/** mutex for thread state */
	mutable boost::mutex _mutex;
	/** condition to manage thread wakeups */
	boost::condition _condition;
	/** the data of the last written frame, or 0 if there isn't one */
	boost::shared_ptr<const EncodedData> _last_written;
	/** the index of the last written frame */
	int _last_written_frame;
	/** maximum number of frames to hold in memory, for when we are managing
	    ordering
	*/
	static const int _maximum_frames_in_memory;

	/** number of FULL written frames */
	int _full_written;
	/** number of FAKE written frames */
	int _fake_written;
	/** number of REPEAT written frames */
	int _repeat_written;
	/** number of frames pushed to disk and then recovered
	    due to the limit of frames to be held in memory.
	*/
	int _pushed_to_disk;
	
	boost::shared_ptr<libdcp::MonoPictureAsset> _picture_asset;
	boost::shared_ptr<libdcp::MonoPictureAssetWriter> _picture_asset_writer;
	boost::shared_ptr<libdcp::SoundAsset> _sound_asset;
	boost::shared_ptr<libdcp::SoundAssetWriter> _sound_asset_writer;
};