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
123
124
125
126
127
128
129
130
131
|
/*
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.
*/
#ifndef DVDOMATIC_ENCODER_H
#define DVDOMATIC_ENCODER_H
/** @file src/encoder.h
* @brief Parent class for classes which can encode video and audio frames.
*/
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread.hpp>
#include <boost/optional.hpp>
#include <list>
#include <stdint.h>
extern "C" {
#include <libavutil/samplefmt.h>
}
#ifdef HAVE_SWRESAMPLE
extern "C" {
#include <libswresample/swresample.h>
}
#endif
#include "util.h"
#include "video_sink.h"
#include "audio_sink.h"
class Image;
class Subtitle;
class AudioBuffers;
class Film;
class ServerDescription;
class DCPVideoFrame;
class EncodedData;
class Writer;
/** @class Encoder
* @brief Encoder to J2K and WAV for DCP.
*
* Video is supplied to process_video as YUV frames, and audio
* is supplied as uncompressed PCM in blocks of various sizes.
*/
class Encoder : public VideoSink, public AudioSink
{
public:
Encoder (boost::shared_ptr<const Film> f);
virtual ~Encoder ();
/** Called to indicate that a processing run is about to begin */
virtual void process_begin ();
/** Call with a frame of video.
* @param i Video frame image.
* @param same true if i is the same as the last time we were called.
* @param s A subtitle that should be on this frame, or 0.
*/
void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s);
/** Call with some audio data */
void process_audio (boost::shared_ptr<AudioBuffers>);
/** Called when a processing run has finished */
virtual void process_end ();
float current_frames_per_second () const;
bool skipping () const;
int video_frames_out () const;
private:
void frame_done ();
void frame_skipped ();
void write_audio (boost::shared_ptr<const AudioBuffers> audio);
void encoder_thread (ServerDescription *);
void terminate_worker_threads ();
/** Film that we are encoding */
boost::shared_ptr<const Film> _film;
/** Mutex for _time_history, _just_skipped and _last_frame */
mutable boost::mutex _history_mutex;
/** List of the times of completion of the last _history_size frames;
first is the most recently completed.
*/
std::list<struct timeval> _time_history;
/** Number of frames that we should keep history for */
static int const _history_size;
/** true if the last frame we processed was skipped (because it was already done) */
bool _just_skipped;
/** Number of video frames received so far */
SourceFrame _video_frames_in;
/** Number of video frames written for the DCP so far */
int _video_frames_out;
#if HAVE_SWRESAMPLE
SwrContext* _swr_context;
#endif
bool _have_a_real_frame;
bool _terminate_encoder;
std::list<boost::shared_ptr<DCPVideoFrame> > _encode_queue;
std::list<boost::thread *> _worker_threads;
mutable boost::mutex _worker_mutex;
boost::condition _worker_condition;
boost::shared_ptr<Writer> _writer;
};
#endif
|