mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-08 18:39:54 +00:00
2f0cc8ec30
Original commit message from CVS: Moved from gst-plugins/ext/mplex/. See that directory for older changelogs.
194 lines
5.1 KiB
C++
194 lines
5.1 KiB
C++
|
||
/*
|
||
* 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:
|
||
*/
|