diff options
Diffstat (limited to 'gst-libs/ext/mplex/stillsstream.cc')
-rw-r--r-- | gst-libs/ext/mplex/stillsstream.cc | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/gst-libs/ext/mplex/stillsstream.cc b/gst-libs/ext/mplex/stillsstream.cc new file mode 100644 index 00000000..1b6d10b3 --- /dev/null +++ b/gst-libs/ext/mplex/stillsstream.cc @@ -0,0 +1,194 @@ + +/* + * stillsstreams.c: Class for elemenary still video streams + * Most functionality is inherited from VideoStream + * + * Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com> + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include <format_codes.h> + +#include "stillsstream.hh" +#include "outputstream.hh" +#include <cassert> + +void +StillsStream::Init () +{ + int stream_id = 0; + int buffer_size = 0; + + SetBufSize (4 * 1024 * 1024); + InitAUbuffer (); + ScanFirstSeqHeader (); + + mjpeg_debug ("SETTING video buffer to %d", muxinto.video_buffer_size); + switch (opt_mux_format) { + case MPEG_FORMAT_VCD_STILL: + if (horizontal_size > 352) { + stream_id = VIDEO_STR_0 + 2; + buffer_size = vbv_buffer_size * 2048; + mjpeg_info ("Stills Stream %02x: high-resolution VCD stills %d KB each", + stream_id, buffer_size); + if (buffer_size < 46 * 1024) + mjpeg_error_exit1 + ("I Can't multiplex high-res stills smaller than normal res stills - sorry!"); + + } else { + stream_id = VIDEO_STR_0 + 1; + buffer_size = 46 * 1024; + mjpeg_info ("Stills Stream %02x: normal VCD stills", stream_id); + } + break; + case MPEG_FORMAT_SVCD_STILL: + if (horizontal_size > 480) { + stream_id = VIDEO_STR_0 + 1; + buffer_size = 230 * 1024; + mjpeg_info ("Stills Stream %02x: high-resolution SVCD stills.", stream_id); + } else { + stream_id = VIDEO_STR_0 + 1; + buffer_size = 230 * 1024; + mjpeg_info ("Stills Stream %02x: normal-resolution SVCD stills.", stream_id); + } + break; + } + + + MuxStream::Init (stream_id, 1, // Buffer scale + buffer_size, 0, // Zero stuffing + muxinto.buffers_in_video, muxinto.always_buffers_in_video); + + /* Skip to the end of the 1st AU (*2nd* Picture start!) + */ + AU_hdr = SEQUENCE_HEADER; + AU_pict_data = 0; + AU_start = 0LL; + + OutputSeqhdrInfo (); + +} + + + + +/* + * Compute DTS / PTS for a VCD/SVCD Stills sequence + * TODO: Very crude. Simply assumes each still stays for the specified + * frame interval and that enough run-in delay is present for the first + * frame to be loaded. + * + */ + +void +StillsStream::NextDTSPTS (clockticks & DTS, clockticks & PTS) +{ + clockticks interval = static_cast < clockticks > + (intervals->NextFrameInterval () * CLOCKS / frame_rate); + clockticks time_for_xfer; + + muxinto.ByteposTimecode (BufferSize (), time_for_xfer); + + DTS = current_PTS + time_for_xfer; // This frame decoded just after + // Predecessor completed. + PTS = current_PTS + time_for_xfer + interval; + current_PTS = PTS; + current_DTS = DTS; +} + +/* + * VCD mixed stills segment items have the constraint that both stills + * streams must end together. To do this each stream has to know + * about its "sibling". + * + */ + +void +VCDStillsStream::SetSibling (VCDStillsStream * _sibling) +{ + assert (_sibling != 0); + sibling = _sibling; + if (sibling->stream_id == stream_id) { + mjpeg_error_exit1 ("VCD mixed stills stream cannot contain two streams of the same type!"); + } + +} + +/* + * Check if we've reached the last sector of the last AU. Note: that + * we know no PTS/DTS time-stamps will be needed because no new AU + * will appear in the last sector. WARNING: We assume a still won't + * fit into a single secotr. + * + */ + +bool +VCDStillsStream::LastSectorLastAU () +{ + return (Lookahead () == 0 && + au_unsent <= muxinto.PacketPayload (*this, buffers_in_header, false, false) + ); +} + + +/* + * The requirement that VCD mixed stills segment items constituent streams + * end together means we can't mux the last sector of the last AU of + * such streams until its sibling has already completed muxing or is + * also ready to mux the last sector of its last AU. + * + * NOTE: Will not work right if sector_align_iframe_AUs not set as this + * will allow multiple AU's in a sector. + * + */ + + +bool +VCDStillsStream::MuxPossible () +{ + if (bufmodel.Size () < au_unsent) { + mjpeg_error_exit1 + ("Illegal VCD still: larger than maximum permitted by its buffering parameters!"); + } + if (RunOutComplete () || bufmodel.Space () < au_unsent) { + return false; + } + + if (LastSectorLastAU ()) { + if (sibling != 0) { + if (!stream_mismatch_warned && sibling->NextAUType () != NOFRAME) { + mjpeg_warn ("One VCD stills stream runs significantly longer than the other!"); + mjpeg_warn ("Simultaneous stream ending recommended by standard not possible"); + return true; + } + return sibling->MuxCompleted () || sibling->LastSectorLastAU (); + } else + return true; + } else + return true; +} + + + + +/* + * Local variables: + * c-file-style: "stroustrup" + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ |