1 
2 /*
3  *  inptstrm.c:  Members of input stream classes related to muxing out into
4  *               the output stream.
5  *
6  *  Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
7  *
8  *
9  *  This program is free software; you can redistribute it and/or
10  *  modify it under the terms of version 2 of the GNU General Public License
11  *  as published by the Free Software Foundation.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22 
23 
24 #include <config.h>
25 #include <assert.h>
26 
27 #include "mjpeg_types.h"
28 #include "videostrm.hpp"
29 #include "multiplexor.hpp"
30 
VideoStream(IBitStream & ibs,VideoParams * parms,Multiplexor & into)31 VideoStream::VideoStream(IBitStream &ibs, VideoParams *parms,
32                          Multiplexor &into ) :
33 	ElementaryStream( ibs, into, ElementaryStream::video ),
34 	num_sequence(0),
35 	num_seq_end(0),
36 	num_pictures(0),
37 	num_groups(0),
38 	dtspts_for_all_au( into.dtspts_for_all_vau ),
39     gop_control_packet( false ),
40     parms(parms)
41 {
42 	prev_offset=0;
43     decoding_order=0;
44 	fields_presented=0;
45     group_start_pic=0;
46 	group_start_field=0;
47     temporal_reference=0;
48 	pulldown_32 = 0;
49     temporal_reference = -1;   // Needed to recognise 2nd field of 1st
50                                // frame in a field pic sequence
51 	last_buffered_AU=0;
52 	max_bits_persec = 0;
53 	AU_hdr = SEQUENCE_HEADER;  /* GOP or SEQ Header starting AU? */
54 	for( int i =0; i<4; ++i )
55 		num_frames[i] = avg_frames[i] = 0;
56     FRAME_CHUNK = 6;
57 
58 }
59 
Probe(IBitStream & bs)60 bool VideoStream::Probe(IBitStream &bs )
61 {
62     return bs.GetBits( 32)  == 0x1b3;
63 }
64 
65 /*********************************
66  * Signals when video stream has completed mux run-out specified
67  * in associated mux stream.   Run-out is always to complete GOP's.
68  *********************************/
69 
RunOutComplete()70 bool VideoStream::RunOutComplete()
71 {
72 
73 	return (au_unsent == 0 ||
74 			( muxinto.running_out &&
75 			  au->type == IFRAME && RequiredPTS() >= muxinto.runout_PTS));
76 }
77 
78 /*********************************
79  * Signals if it is permissible/possible to Mux out a sector from the Stream.
80  * The universal constraints that muxing should not be complete and that
81  * that the reciever buffer should have sufficient it also insists that
82  * the muxed data won't hang around in the receiver buffer for more than
83  * one second.  This is mainly for the benefit of (S)VCD and DVD applications
84  * where long delays mess up random access.
85  *******************************/
86 
MuxPossible(clockticks currentSCR)87 bool VideoStream::MuxPossible( clockticks currentSCR )
88 {
89 	return ( ElementaryStream::MuxPossible(currentSCR) &&
90              RequiredDTS() < currentSCR + max_STD_buffer_delay );
91 }
92 
93 
AUMuxed(bool first_in_sector)94 void VideoStream::AUMuxed( bool first_in_sector )
95 {
96     //DEBUG
97     //mjpeg_info( "VidMuxed: %d %lld ", au->dorder, RequiredDTS()/300 );
98 }
99 
100 
101 /*********************************
102  * Work out the timestamps to be set in the header of sectors starting
103  * new AU's.
104  *********************************/
105 
NewAUTimestamps(int AUtype)106 uint8_t VideoStream::NewAUTimestamps( int AUtype )
107 {
108 	uint8_t timestamps;
109     if( AUtype == BFRAME)
110         timestamps=TIMESTAMPBITS_PTS;
111     else
112         timestamps=TIMESTAMPBITS_PTS_DTS;
113 
114     if( muxinto.timestamp_iframe_only && AUtype != IFRAME)
115         timestamps=TIMESTAMPBITS_NO;
116     return timestamps;
117 }
118 
119 /*********************************
120  * Work out the buffer records to be set in the header of sectors
121  * starting new AU's.
122  *********************************/
123 
NewAUBuffers(int AUtype)124 bool VideoStream::NewAUBuffers( int AUtype )
125 {
126     return buffers_in_header &
127         !(muxinto.video_buffers_iframe_only && AUtype != IFRAME);
128 }
129 
130 /********************************
131  *
132  * Check if the next sector could potentially include parts of AUs
133  * following a sequence end marker... in this case a run-out may be needed
134  *
135  *******************************/
136 
SeqEndRunOut()137 bool VideoStream::SeqEndRunOut()
138 {
139     unsigned int payload = au_unsent;
140     unsigned int ahead = 0;
141     AUnit *next_au = au;
142     for(;;)
143     {
144         if( next_au->end_seq || payload >= muxinto.sector_size)
145             break;
146         ++ahead;
147         next_au = Lookahead(ahead);
148         if( next_au == 0 )
149             break;
150         payload += next_au->PayloadSize();
151     }
152 
153     // We don't need to start run-out if the next sector cannot contain
154     // next sequence or there is no next sequence (no AU after the one with
155     // the sequence end marker
156     return next_au != 0 && next_au->end_seq
157         && payload < muxinto.sector_size
158         && Lookahead(ahead+1) != 0;
159 
160 }
161 
162 /********************************
163  *
164  * Check if the next sector could potentially include a seq_end marker
165  *
166  *******************************/
167 
NextIFrame()168 const AUnit *VideoStream::NextIFrame()
169 {
170     unsigned int ahead = 0;
171     AUnit *au_ahead = Lookahead(ahead);
172     while( au_ahead != 0 && au_ahead->type != IFRAME
173            && ahead < MAX_GOP_LENGTH )
174     {
175         ++ahead;
176         au_ahead = Lookahead(ahead);
177     }
178     return au_ahead;
179 }
180 
181 /********************************
182  *
183  * Calculate how much payload can be muxed next sector without
184  * including the next IFRAME.
185  *
186  *******************************/
187 
ExcludeNextIFramePayload()188 unsigned int VideoStream::ExcludeNextIFramePayload()
189 {
190     unsigned int payload = au_unsent;
191     unsigned int ahead = 0;
192     AUnit *au_ahead;
193     for(;;)
194     {
195         au_ahead = Lookahead(ahead);
196         if( au_ahead == 0 || payload >= muxinto.sector_size || au_ahead->type == IFRAME )
197             break;
198         payload += au_ahead->PayloadSize();
199         ++ahead;
200     }
201     assert( eoscan || au_ahead != 0 );
202     return payload;
203 }
204 
205 /******************************************************************
206 	Output_Video
207 	generiert Pack/Sys_Header/Packet Informationen aus dem
208 	Video Stream und speichert den so erhaltenen Sektor ab.
209 
210 	generates Pack/Sys_Header/Packet information from the
211 	video stream and writes out the new sector
212 ******************************************************************/
213 
OutputSector()214 void VideoStream::OutputSector ( )
215 
216 {
217 	unsigned int max_packet_payload;
218 	unsigned int actual_payload;
219 	unsigned int old_au_then_new_payload;
220 	clockticks  DTS,PTS;
221     int autype;
222 
223 	max_packet_payload = 0;	/* 0 = Fill sector */
224   	/*
225        I-frame aligning.  For the last AU of segment or for formats
226        with ACCESS-POINT sectors where I-frame (and preceding headers)
227        are sector aligned.
228 
229        We need to look ahead to see how much we may put into the current packet
230        without without touching the next I-frame (which is supposed to be
231        placed at the start of its own sector).
232 
233        N.b.runout_PTS is the PTS of the after which the next I frame
234        marks the start of the next sequence.
235 	*/
236 
237     /* TODO finish this: Need to look-ahead sufficiently far to
238        guarantee finding an I-FRAME even if its predecessors are very
239        small.
240     */
241 	if( muxinto.sector_align_iframeAUs || muxinto.running_out )
242 	{
243 		max_packet_payload = ExcludeNextIFramePayload();
244 	}
245 
246 	/* Figure out the threshold payload size below which we can fit more
247 	   than one AU into a packet N.b. because fitting more than one in
248 	   imposses an overhead of additional header fields so there is a
249 	   dead spot where we *have* to stuff the packet rather than start
250 	   fitting in an extra AU.  Slightly over-conservative in the case
251 	   of the last packet...  */
252 
253 	old_au_then_new_payload = muxinto.PacketPayload( *this,
254 					buffers_in_header,
255 					true, true);
256 
257 	/* CASE: Packet starts with new access unit			*/
258 	if (new_au_next_sec  )
259 	{
260         autype = AUType();
261         //
262         // Some types of output format (e.g. DVD) require special
263         // control sectors before the sector starting a new GOP
264         // N.b. this implies muxinto.sector_align_iframeAUs
265         //
266         if( gop_control_packet && autype == IFRAME )
267         {
268             OutputGOPControlSector();
269         }
270 
271         //
272         // If we demand every AU should have its own timestamp
273         // We can't start two in the same sector...
274         //
275         if(  dtspts_for_all_au  && max_packet_payload == 0 )
276             max_packet_payload = au_unsent;
277 
278         PTS = RequiredPTS();
279         DTS = RequiredDTS();
280 		actual_payload =
281 			muxinto.WritePacket ( max_packet_payload,
282 						*this,
283 						NewAUBuffers(autype),
284                                   		PTS, DTS,
285 						NewAUTimestamps(autype) );
286 
287 	}
288 
289 	/* CASE: Packet begins with old access unit, no new one	*/
290 	/*	     can begin in the very same packet					*/
291 
292 	else if ( au_unsent >= old_au_then_new_payload ||
293               (max_packet_payload != 0 && au_unsent >= max_packet_payload) )
294 	{
295 		actual_payload =
296 			muxinto.WritePacket( au_unsent,
297 							*this,
298 							false, 0, 0,
299 							TIMESTAMPBITS_NO );
300 	}
301 
302 	/* CASE: Packet begins with old access unit, a new one	*/
303 	/*	     could begin in the very same packet			*/
304 	else /* if ( !new_au_next_sec  &&
305 			(au_unsent < old_au_then_new_payload)) */
306 	{
307 		/* Is there a new access unit ? */
308 		if( Lookahead() != 0 )
309 		{
310             autype = NextAUType();
311 			if(  dtspts_for_all_au  && max_packet_payload == 0 )
312 				max_packet_payload = au_unsent + Lookahead()->length;
313 
314 			PTS = NextRequiredPTS();
315 			DTS = NextRequiredDTS();
316 
317 			actual_payload =
318 				muxinto.WritePacket ( max_packet_payload,
319 						*this,
320 						NewAUBuffers(autype),
321                                       		PTS, DTS,
322 						NewAUTimestamps(autype) );
323 		}
324 		else
325 		{
326 			actual_payload = muxinto.WritePacket ( au_unsent,
327 							*this, false, 0, 0,
328 							TIMESTAMPBITS_NO);
329 		}
330 	}
331 	++nsec;
332 	buffers_in_header = always_buffers_in_header;
333 }
334 
335 
336 /***********************************************
337    OutputControlSector - Write control sectors prefixing a GOP
338    For "normal" video streams this doesn't happen and so represents
339    a bug and triggers an abort.
340 
341    In DVD's these sectors carry a system header and what is
342    presumably indexing and/or sub-title information in
343    private_stream_2 packets.  I have no idea what to put in here so we
344    simply pad the sector out.
345 ***********************************************/
346 
OutputGOPControlSector()347 void VideoStream::OutputGOPControlSector()
348 {
349     abort();
350 }
351 
352  /******************************************************************
353  *	OutputGOPControlSector
354  *  DVD System headers are carried in peculiar sectors carrying 2
355  *  PrivateStream2 packets.   We're sticking 0's in the packets
356  *  as we have no idea what's supposed to be in there.
357  ******************************************************************/
358 
OutputGOPControlSector()359 void DVDVideoStream::OutputGOPControlSector()
360 {
361     muxinto.OutputDVDPriv2 ();
362 }
363 
364 
365 /*
366  * Local variables:
367  *  c-file-style: "stroustrup"
368  *  tab-width: 4
369  *  indent-tabs-mode: nil
370  * End:
371  */
372