1 #include "packet-processor.hpp"
2 #include "output-drv.hpp"
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
;
20 rate_denum
= _rate_denum
;
21 frame_dropper
= _frame_dropper
;
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
)
37 delete &using_resizer
;
40 int64_t packet_processor::get_real_time(struct packet
& p
)
45 return p
.rp_timestamp
+ audio_delay
;
47 return p
.rp_timestamp
+ subtitle_delay
;
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
) {
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
);
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.
72 f
= new image_frame_rgbx(width
, height
);
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());
92 subtitle_process_gameinfo(hardsubs
, q
);
97 resizer
* rs
= &using_resizer
;
98 image_frame_rgbx
* f
= new image_frame_rgbx(q
);
99 uint64_t ts
= q
.rp_timestamp
;
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
);
108 frame_dropper
->push(ts
, r
);
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
);
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());
135 if(packet_realtime
>= 0) {
136 q
.rp_timestamp
+= subtitle_delay
;
137 distribute_subtitle_callback(q
);
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
))
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
)
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
);