Fix some problems reported by Valgrind
[jpcrr.git] / streamtools / packet-processor.cpp
blob0e19d1924f0e09f3fd3ba3d907204a59b91a6c50
1 #include "packet-processor.hpp"
2 #include "output-drv.hpp"
3 #include <iostream>
5 packet_processor::packet_processor(int64_t _audio_delay, int64_t _subtitle_delay, uint32_t _audio_rate,
6 packet_demux& _demux, uint32_t _width, uint32_t _height, uint32_t _rate_num, uint32_t _rate_denum,
7 uint32_t _dedup_max, resizer& _using_resizer,
8 std::map<std::pair<uint32_t, uint32_t>, resizer*> _special_resizers, std::list<subtitle*> _hardsubs,
9 framerate_reducer* _frame_dropper)
10 : using_resizer(_using_resizer), demux(_demux), dedupper(_dedup_max, _width, _height),
11 audio_timer(_audio_rate), video_timer(_rate_num, _rate_denum)
13 audio_delay = _audio_delay;
14 subtitle_delay = _subtitle_delay;
15 special_resizers = _special_resizers;
16 audio_rate = _audio_rate;
17 width = _width;
18 height = _height;
19 rate_num = _rate_num;
20 rate_denum = _rate_denum;
21 frame_dropper = _frame_dropper;
22 hardsubs = _hardsubs;
23 sequence_length = 0;
24 min_shift = 0;
25 saved_video_frame = NULL;
26 if(min_shift > _audio_delay)
27 min_shift = _audio_delay;
28 if(min_shift > _subtitle_delay)
29 min_shift = _subtitle_delay;
32 packet_processor::~packet_processor()
34 for(std::list<subtitle*>::iterator i = hardsubs.begin(); i != hardsubs.end(); ++i)
35 delete *i;
36 delete &demux;
37 delete &using_resizer;
40 int64_t packet_processor::get_real_time(struct packet& p)
42 switch(p.rp_major) {
43 case 1:
44 case 2:
45 return p.rp_timestamp + audio_delay;
46 case 4:
47 return p.rp_timestamp + subtitle_delay;
48 default:
49 return p.rp_timestamp;
53 void packet_processor::handle_packet(struct packet& q)
55 int64_t packet_realtime = get_real_time(q);
56 int64_t audio_linear_time = packet_realtime - min_shift;
57 //Read the audio data until this packet. Audio_linear_time is always positive.
58 while(audio_timer <= (uint64_t)audio_linear_time) {
59 //Extract sample.
60 sample_number_t v = demux.nextsample();
61 //Send sample only if audio time is really positive.
62 if(audio_linear_time > (int64_t)-min_shift)
63 distribute_audio_callback(v);
64 audio_timer++;
66 //Dump the video data until this packet (fixed fps mode).
67 while(rate_denum > 0 && packet_realtime >= 0 && (int64_t)(uint64_t)video_timer <= packet_realtime) {
68 image_frame_rgbx* f = &frame_dropper->pull((uint64_t)video_timer);
69 if(!f->get_width() || !f->get_height()) {
70 //Replace with valid frame.
71 delete f;
72 f = new image_frame_rgbx(width, height);
75 //Subtitles.
76 for(std::list<subtitle*>::iterator i = hardsubs.begin(); i != hardsubs.end(); ++i)
77 if((*i)->timecode <= video_timer && (*i)->timecode + (*i)->duration > video_timer)
78 render_subtitle(*f, **i);
80 //Write && Free the temporary frames.
81 distribute_video_callback(video_timer, f->get_pixels());
82 delete f;
83 video_timer++;
85 switch(q.rp_major) {
86 case 1:
87 case 2:
88 demux.sendpacket(q);
89 delete &q;
90 break;
91 case 5:
92 subtitle_process_gameinfo(hardsubs, q);
93 delete &q;
94 break;
95 case 0:
96 if(rate_denum > 0) {
97 resizer* rs = &using_resizer;
98 image_frame_rgbx* f = new image_frame_rgbx(q);
99 uint64_t ts = q.rp_timestamp;
100 delete &q;
101 //If special resizer has been defined, use that.
102 std::pair<uint32_t, uint32_t> size = std::make_pair(f->get_width(), f->get_height());
103 if(special_resizers.count(size))
104 rs = special_resizers[size];
105 image_frame_rgbx& r = f->resize(width, height, *rs);
106 if(&r != f)
107 delete f;
108 frame_dropper->push(ts, r);
109 } else {
110 resizer* rs = &using_resizer;
112 //Handle frame immediately.
113 image_frame_rgbx f(q);
114 std::pair<uint32_t, uint32_t> size = std::make_pair(f.get_width(), f.get_height());
115 if(special_resizers.count(size))
116 rs = special_resizers[size];
117 image_frame_rgbx& r = f.resize(width, height, *rs);
119 //Subtitles.
120 for(std::list<subtitle*>::iterator i = hardsubs.begin(); i != hardsubs.end(); ++i)
121 if((*i)->timecode <= q.rp_timestamp &&
122 (*i)->timecode + (*i)->duration > q.rp_timestamp)
123 render_subtitle(r, **i);
125 //Write && Free the temporary frames.
126 if(!dedupper(r.get_pixels()))
127 distribute_video_callback(q.rp_timestamp, r.get_pixels());
128 if(&r != &f)
129 delete &r;
130 delete &q;
132 break;
133 case 4:
134 //Subttitle.
135 if(packet_realtime >= 0) {
136 q.rp_timestamp += subtitle_delay;
137 distribute_subtitle_callback(q);
139 delete &q;
140 break;
141 default:
142 delete &q;
143 break;
147 uint64_t packet_processor::get_last_timestamp()
149 return sequence_length;
152 void packet_processor::send_packet(struct packet& p, uint64_t timebase)
154 p.rp_timestamp += timebase;
155 sequence_length = p.rp_timestamp;
156 //Keep list of unprocessed packets sorted in real time order.
157 int64_t packet_realtime = get_real_time(p);
158 //Find the point to insert before and do the insertion.
159 std::list<packet*>::iterator i = unprocessed.begin();
160 while(i != unprocessed.end() && packet_realtime >= get_real_time(**i))
161 ++i;
162 unprocessed.insert(i, &p);
164 //Read the first packet from the queue.
165 handle_packet(*unprocessed.front());
166 unprocessed.pop_front();
169 void packet_processor::send_end_of_stream()
171 while(!unprocessed.empty()) {
172 handle_packet(*unprocessed.front());
173 unprocessed.pop_front();
177 uint64_t send_stream(packet_processor& p, read_channel& rc, uint64_t timebase)
179 struct packet* q;
180 static uint64_t last_second = 0;
181 while((q = rc.read())) {
182 if((q->rp_timestamp + timebase) / 1000000000 > last_second) {
183 last_second = (q->rp_timestamp + timebase) / 1000000000;
184 std::cerr << "Processed " << last_second << "s." << std::endl;
186 p.send_packet(*q, timebase);
188 return p.get_last_timestamp();
191 packet_processor& create_packet_processor(int64_t _audio_delay, int64_t _subtitle_delay, uint32_t _audio_rate,
192 uint32_t _width, uint32_t _height, uint32_t _rate_num, uint32_t _rate_denum, uint32_t _dedup_max,
193 const std::string& resize_type, std::map<std::pair<uint32_t, uint32_t>, std::string> _special_resizers,
194 int argc, char** argv, framerate_reducer* frame_dropper)
196 hardsub_settings stsettings;
197 std::map<std::pair<uint32_t, uint32_t>, resizer*> special_resizers;
198 resizer& _using_resizer = resizer_factory::make_by_type(resize_type);
199 mixer& mix = *new mixer();
200 packet_demux& ademux = *new packet_demux(mix, _audio_rate);
201 process_audio_resampler_options(ademux, "--audio-mixer-", argc, argv);
202 std::list<subtitle*> subtitles = process_hardsubs_options(stsettings, "--video-hardsub-", argc, argv);
204 for(std::map<std::pair<uint32_t, uint32_t>, std::string>::iterator i = _special_resizers.begin();
205 i != _special_resizers.end(); ++i)
206 special_resizers[i->first] = &resizer_factory::make_by_type(i->second);
208 return *new packet_processor(_audio_delay, _subtitle_delay, _audio_rate, ademux, _width, _height, _rate_num,
209 _rate_denum, _dedup_max, _using_resizer, special_resizers, subtitles, frame_dropper);