1 
2 /*
3  *  stillsstreams.c: Class for elemenary still video streams
4  *                   Most functionality is inherited from VideoStream
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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <format_codes.h>
29 
30 #include "stillsstream.hpp"
31 #include "interact.hpp"
32 #include "multiplexor.hpp"
33 
Init()34 void StillsStream::Init ( )
35 {
36 	int stream_id = -1;
37 	int buffer_size = -1;
38 
39 	SetBufSize( 4*1024*1024 );
40 	ScanFirstSeqHeader();
41 
42 	mjpeg_debug( "Stills: Video buffer suggestion ignored!" );
43 	switch( muxinto.mux_format )
44 	{
45 	case  MPEG_FORMAT_VCD_STILL :
46 		if( horizontal_size > 352 )
47 		{
48 			stream_id = VIDEO_STR_0+2 ;
49 			buffer_size = vbv_buffer_size*2048;
50 			mjpeg_info( "Stills Stream %02x: high-resolution VCD stills %d KB each",
51 						stream_id,
52 						buffer_size );
53 			if( buffer_size < 46*1024 )
54 				mjpeg_error_exit1( "I Can't multiplex high-res stills smaller than normal res stills - sorry!");
55 
56 		}
57 		else
58 		{
59 			stream_id = VIDEO_STR_0+1 ;
60 			buffer_size = 46*1024;
61 			mjpeg_info( "Stills Stream %02x: normal VCD stills", stream_id );
62 		}
63 		break;
64 	case MPEG_FORMAT_SVCD_STILL :
65 		if( horizontal_size > 480 )
66 		{
67 			stream_id = VIDEO_STR_0+1;
68 			buffer_size = 230*1024;
69 			mjpeg_info( "Stills Stream %02x: high-resolution SVCD stills.",
70 						stream_id );
71 		}
72 		else
73 		{
74 			stream_id = VIDEO_STR_0+1 ;
75 			buffer_size = 230*1024;
76 			mjpeg_info( "Stills Stream %02x: normal-resolution SVCD stills.", stream_id );
77 		}
78 		break;
79 	default:
80 		mjpeg_error_exit1( "Only SVCD and VCD Still currently supported");
81 	}
82 
83 
84 	MuxStream::Init( stream_id,
85 					 1,  // Buffer scale
86 					 buffer_size,
87 					 0,  // Zero stuffing
88 					 muxinto.buffers_in_video,
89 					 muxinto.always_buffers_in_video);
90 
91 	/* Skip to the end of the 1st AU (*2nd* Picture start!)
92 	*/
93 	AU_hdr = SEQUENCE_HEADER;
94 	AU_pict_data = 0;
95 	AU_start = 0;
96 
97     OutputSeqhdrInfo();
98 
99 }
100 
101 
102 
103 
104 /*
105  * Compute DTS / PTS for a VCD/SVCD Stills sequence
106  * TODO: Very crude. Simply assumes each still stays for the specified
107  * frame interval and that enough run-in delay is present for the first
108  * frame to be loaded.
109  *
110  */
111 
NextDTSPTS()112 void StillsStream::NextDTSPTS( )
113 {
114     StillsParams *sparms = static_cast<StillsParams*>(parms);
115 
116 	clockticks interval = static_cast<clockticks>
117 		(sparms->Intervals()->NextFrameInterval() * CLOCKS / frame_rate);
118 	clockticks time_for_xfer;
119 	muxinto.ByteposTimecode( BufferSize(), time_for_xfer );
120 
121 	access_unit.DTS = current_PTS + time_for_xfer;	// This frame decoded just after
122 	                                    // Predecessor completed.
123 	access_unit.PTS = current_PTS + time_for_xfer + interval;
124 	current_PTS = access_unit.PTS;
125 	current_DTS = access_unit.DTS;
126     fields_presented += 2;
127 }
128 
129 /*
130  * VCD mixed stills segment items have the constraint that both stills
131  * streams must end together.  To do this each stream has to know
132  * about its "sibling".
133  *
134  */
135 
SetSibling(VCDStillsStream * _sibling)136 void VCDStillsStream::SetSibling( VCDStillsStream *_sibling )
137 {
138 	assert( _sibling != 0 );
139 	sibling = _sibling;
140 	if( sibling->stream_id == stream_id )
141 	{
142 		mjpeg_error_exit1("VCD mixed stills stream cannot contain two streams of the same type!");
143 	}
144 
145 }
146 
147 /*
148  * Check if we've reached the last sector of the last AU.  Note: that
149  * we know no PTS/DTS time-stamps will be needed because no new AU
150  * will appear in the last sector.  WARNING: We assume a still won't
151  * fit into a single secotr.
152  *
153  */
154 
LastSectorLastAU()155 bool VCDStillsStream::LastSectorLastAU()
156 {
157 	return ( Lookahead() == 0 &&
158 			 au_unsent <= muxinto.PacketPayload( *this,
159 												 buffers_in_header,
160 												 false, false )
161 		);
162 }
163 
164 
165 /*
166  * The requirement that VCD mixed stills segment items constituent streams
167  * end together means we can't mux the last sector of the last AU of
168  * such streams until its sibling has already completed muxing or is
169  * also ready to mux the last sector of its last AU.
170  *
171  * NOTE: Will not work right if sector_align_iframe_AUs not set as this
172  * will allow multiple AU's in  a sector.
173  *
174  */
175 
176 
MuxPossible(clockticks currentSCR)177 bool VCDStillsStream::MuxPossible(clockticks currentSCR)
178 {
179     if( bufmodel.Size() < au_unsent )
180     {
181         mjpeg_error_exit1( "Illegal VCD still: larger than maximum permitted by its buffering parameters!");
182     }
183 	if (RunOutComplete() ||	bufmodel.Space() < au_unsent)
184 	{
185 		return false;
186 	}
187 
188 	if( LastSectorLastAU() )
189 	{
190 		if( sibling != 0 )
191         {
192             if( !stream_mismatch_warned && sibling->NextAUType() != NOFRAME  )
193             {
194                 mjpeg_warn( "One VCD stills stream runs significantly longer than the other!");
195                 mjpeg_warn( "Simultaneous stream ending recommended by standard not possible" );
196                 return true;
197             }
198             return sibling->MuxCompleted() || sibling->LastSectorLastAU();
199         }
200         else
201             return true;
202 	}
203 	else
204 		return true;
205 }
206 
207 
208 
209 
210 /*
211  * Local variables:
212  *  c-file-style: "stroustrup"
213  *  tab-width: 4
214  *  indent-tabs-mode: nil
215  * End:
216  */
217