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 : 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
;
19 rate_denum
= _rate_denum
;
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
)
36 int64_t packet_processor::get_real_time(struct packet
& p
)
41 return p
.rp_timestamp
+ audio_delay
;
43 return p
.rp_timestamp
+ subtitle_delay
;
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
) {
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
);
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
) {
65 resizer
* rs
= &using_resizer
;
66 //Parse the frame from saved packet.
68 f
= new image_frame_rgbx(*saved_video_frame
);
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
);
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());
97 subtitle_process_gameinfo(hardsubs
, q
);
101 if(saved_video_frame
)
102 delete saved_video_frame
;
103 saved_video_frame
= &q
;
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
);
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());
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
))
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
)
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
);