Allow size-specific resizers
[jpcrr.git] / streamtools / packet-processor.cpp
blob53a091639eeabb2f467820cd5c074ae43721643e
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 : using_resizer(_using_resizer), demux(_demux), dedupper(_dedup_max, _width, _height),
10 audio_timer(_audio_rate), video_timer(_rate_num, _rate_denum)
12 audio_delay = _audio_delay;
13 subtitle_delay = _subtitle_delay;
14 special_resizers = _special_resizers;
15 audio_rate = _audio_rate;
16 width = _width;
17 height = _height;
18 rate_num = _rate_num;
19 rate_denum = _rate_denum;
20 hardsubs = _hardsubs;
21 sequence_length = 0;
22 min_shift = 0;
23 saved_video_frame = NULL;
24 if(min_shift > _audio_delay)
25 min_shift = _audio_delay;
26 if(min_shift > _subtitle_delay)
27 min_shift = _subtitle_delay;
30 packet_processor::~packet_processor()
32 for(std::list<subtitle*>::iterator i = hardsubs.begin(); i != hardsubs.end(); ++i)
33 delete *i;
36 int64_t packet_processor::get_real_time(struct packet& p)
38 switch(p.rp_major) {
39 case 1:
40 case 2:
41 return p.rp_timestamp + audio_delay;
42 case 4:
43 return p.rp_timestamp + subtitle_delay;
44 default:
45 return p.rp_timestamp;
49 void packet_processor::handle_packet(struct packet& q)
51 int64_t packet_realtime = get_real_time(q);
52 int64_t audio_linear_time = packet_realtime - min_shift;
53 //Read the audio data until this packet. Audio_linear_time is always positive.
54 while(audio_timer <= (uint64_t)audio_linear_time) {
55 //Extract sample.
56 sample_number_t v = demux.nextsample();
57 //Send sample only if audio time is really positive.
58 if(audio_linear_time > (int64_t)-min_shift)
59 distribute_audio_callback(v);
60 audio_timer++;
62 //Dump the video data until this packet (fixed fps mode).
63 while(rate_denum > 0 && packet_realtime >= 0 && (int64_t)(uint64_t)video_timer <= packet_realtime) {
64 image_frame_rgbx* f;
65 resizer* rs = &using_resizer;
66 //Parse the frame from saved packet.
67 if(saved_video_frame)
68 f = new image_frame_rgbx(*saved_video_frame);
69 else
70 f = new image_frame_rgbx(0, 0);
71 //If special resizer has been defined, use that.
72 std::pair<uint32_t, uint32_t> size = std::make_pair(f->get_width(), f->get_height());
73 if(special_resizers.count(size))
74 rs = special_resizers[size];
76 image_frame_rgbx& r = f->resize(width, height, *rs);
78 //Subtitles.
79 for(std::list<subtitle*>::iterator i = hardsubs.begin(); i != hardsubs.end(); ++i)
80 if((*i)->timecode <= video_timer && (*i)->timecode + (*i)->duration > video_timer)
81 render_subtitle(r, **i);
83 //Write && Free the temporary frames.
84 distribute_video_callback(video_timer, r.get_pixels());
85 if(&r != f)
86 delete &r;
87 delete f;
88 video_timer++;
90 switch(q.rp_major) {
91 case 1:
92 case 2:
93 demux.sendpacket(q);
94 delete &q;
95 break;
96 case 5:
97 subtitle_process_gameinfo(hardsubs, q);
98 break;
99 case 0:
100 if(rate_denum > 0) {
101 if(saved_video_frame)
102 delete saved_video_frame;
103 saved_video_frame = &q;
104 } else {
105 resizer* rs = &using_resizer;
107 //Handle frame immediately.
108 image_frame_rgbx f(q);
109 std::pair<uint32_t, uint32_t> size = std::make_pair(f.get_width(), f.get_height());
110 if(special_resizers.count(size))
111 rs = special_resizers[size];
112 image_frame_rgbx& r = f.resize(width, height, *rs);
114 //Subtitles.
115 for(std::list<subtitle*>::iterator i = hardsubs.begin(); i != hardsubs.end(); ++i)
116 if((*i)->timecode <= q.rp_timestamp &&
117 (*i)->timecode + (*i)->duration > q.rp_timestamp)
118 render_subtitle(r, **i);
120 //Write && Free the temporary frames.
121 if(!dedupper(r.get_pixels()))
122 distribute_video_callback(q.rp_timestamp, r.get_pixels());
123 if(&r != &f)
124 delete &r;
125 delete &q;
127 break;
128 case 4:
129 //Subttitle.
130 if(packet_realtime >= 0) {
131 q.rp_timestamp += subtitle_delay;
132 distribute_subtitle_callback(q);
137 uint64_t packet_processor::get_last_timestamp()
139 return sequence_length;
142 void packet_processor::send_packet(struct packet& p, uint64_t timebase)
144 p.rp_timestamp += timebase;
145 sequence_length = p.rp_timestamp;
146 //Keep list of unprocessed packets sorted in real time order.
147 int64_t packet_realtime = get_real_time(p);
148 //Find the point to insert before and do the insertion.
149 std::list<packet*>::iterator i = unprocessed.begin();
150 while(i != unprocessed.end() && packet_realtime >= get_real_time(**i))
151 ++i;
152 unprocessed.insert(i, &p);
154 //Read the first packet from the queue.
155 handle_packet(*unprocessed.front());
156 unprocessed.pop_front();
159 void packet_processor::send_end_of_stream()
161 while(!unprocessed.empty()) {
162 handle_packet(*unprocessed.front());
163 unprocessed.pop_front();
167 uint64_t send_stream(packet_processor& p, read_channel& rc, uint64_t timebase)
169 struct packet* q;
170 static uint64_t last_second = 0;
171 while((q = rc.read())) {
172 if((q->rp_timestamp + timebase) / 1000000000 > last_second) {
173 last_second = (q->rp_timestamp + timebase) / 1000000000;
174 std::cerr << "Processed " << last_second << "s." << std::endl;
176 p.send_packet(*q, timebase);
178 return p.get_last_timestamp();
181 packet_processor& create_packet_processor(int64_t _audio_delay, int64_t _subtitle_delay, uint32_t _audio_rate,
182 uint32_t _width, uint32_t _height, uint32_t _rate_num, uint32_t _rate_denum, uint32_t _dedup_max,
183 const std::string& resize_type, std::map<std::pair<uint32_t, uint32_t>, std::string> _special_resizers,
184 int argc, char** argv)
186 hardsub_settings stsettings;
187 std::map<std::pair<uint32_t, uint32_t>, resizer*> special_resizers;
188 resizer& _using_resizer = resizer_factory::make_by_type(resize_type);
189 mixer& mix = *new mixer();
190 packet_demux& ademux = *new packet_demux(mix, _audio_rate);
191 process_audio_resampler_options(ademux, "--audio-mixer-", argc, argv);
192 std::list<subtitle*> subtitles = process_hardsubs_options(stsettings, "--video-hardsub-", argc, argv);
194 for(std::map<std::pair<uint32_t, uint32_t>, std::string>::iterator i = _special_resizers.begin();
195 i != _special_resizers.end(); ++i)
196 special_resizers[i->first] = &resizer_factory::make_by_type(i->second);
198 return *new packet_processor(_audio_delay, _subtitle_delay, _audio_rate, ademux, _width, _height, _rate_num,
199 _rate_denum, _dedup_max, _using_resizer, special_resizers, subtitles);