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