2003-07-26 03:01:58 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2003-11-07 12:47:02 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-07-26 03:01:58 +00:00
|
|
|
|
#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:
|
|
|
|
|
*/
|