Windows2003-3790/enduser/netmeeting/av/codecs/dec/dech261/slib_api.c
2020-09-30 16:53:55 +02:00

4035 lines
149 KiB
C

/*
* @DEC_COPYRIGHT@
*/
/*
* HISTORY
* $Log: slib_api.c,v $
* Revision 1.1.6.35 1996/12/13 18:19:04 Hans_Graves
* Update Audio and Video timestamp correctly.
* [1996/12/13 18:09:02 Hans_Graves]
*
* Revision 1.1.6.34 1996/12/12 20:54:44 Hans_Graves
* Timestamp fixes after seek to Key frames.
* [1996/12/12 20:52:06 Hans_Graves]
*
* Revision 1.1.6.33 1996/12/10 19:46:02 Hans_Graves
* Fix floating division error when audio only.
* [1996/12/10 19:45:03 Hans_Graves]
*
* Revision 1.1.6.32 1996/12/10 19:21:55 Hans_Graves
* Made calculate video positions more accurate using slibFrameToTime100().
* [1996/12/10 19:16:20 Hans_Graves]
*
* Revision 1.1.6.31 1996/12/05 20:10:15 Hans_Graves
* Add gradual increase or decrease of framerates according to timestamps.
* [1996/12/05 20:06:57 Hans_Graves]
*
* Revision 1.1.6.30 1996/12/04 22:34:28 Hans_Graves
* Put limit on data used by Sv/SaDecompressBegin().
* [1996/12/04 22:14:33 Hans_Graves]
*
* Revision 1.1.6.29 1996/12/03 23:15:13 Hans_Graves
* MME-1498: Made seeks with PERCENT100 more accurate
* [1996/12/03 23:10:43 Hans_Graves]
*
* Revision 1.1.6.28 1996/12/03 00:08:31 Hans_Graves
* Handling of End Of Sequence points. Added PERCENT100 support.
* [1996/12/03 00:05:59 Hans_Graves]
*
* Revision 1.1.6.27 1996/11/21 23:34:21 Hans_Graves
* Handle MPEG B frames better when seeking.
* [1996/11/21 23:28:18 Hans_Graves]
*
* Revision 1.1.6.26 1996/11/20 02:15:09 Hans_Graves
* Added SEEK_AHEAD. Removed old code.
* [1996/11/20 02:10:43 Hans_Graves]
*
* Revision 1.1.6.25 1996/11/18 23:07:21 Hans_Graves
* Remove MaxVideoLength usage.
* [1996/11/18 22:55:56 Hans_Graves]
*
* Make use of presentation timestamps. Make seeking time-based.
* [1996/11/18 22:47:30 Hans_Graves]
*
* Revision 1.1.6.24 1996/11/14 21:49:26 Hans_Graves
* AC3 buffering fixes.
* [1996/11/14 21:43:20 Hans_Graves]
*
* Revision 1.1.6.23 1996/11/13 16:10:54 Hans_Graves
* AC3 recognition of byte reversed streams in slibGetDataFormat().
* [1996/11/13 16:03:14 Hans_Graves]
*
* Revision 1.1.6.22 1996/11/11 18:21:03 Hans_Graves
* More AC3 support changes.
* [1996/11/11 17:59:01 Hans_Graves]
*
* Revision 1.1.6.21 1996/11/08 21:51:02 Hans_Graves
* Added AC3 support. Better seperation of stream types.
* [1996/11/08 21:27:57 Hans_Graves]
*
* Revision 1.1.6.20 1996/10/31 00:08:51 Hans_Graves
* Fix skipping data after RESET with MPEG video only streams.
* [1996/10/31 00:07:08 Hans_Graves]
*
* Revision 1.1.6.19 1996/10/28 23:16:42 Hans_Graves
* MME-0145?, Fix artifacts when using SlibReadData() at a new position. Jump to first GOP.
* [1996/10/28 23:13:01 Hans_Graves]
*
* Revision 1.1.6.18 1996/10/28 17:32:28 Hans_Graves
* MME-1402, 1431, 1435: Timestamp related changes.
* [1996/10/28 17:22:58 Hans_Graves]
*
* Revision 1.1.6.17 1996/10/17 00:23:32 Hans_Graves
* Fix buffer problems after SlibQueryData() calls.
* [1996/10/17 00:19:05 Hans_Graves]
*
* Revision 1.1.6.16 1996/10/15 17:34:09 Hans_Graves
* Added MPEG-2 Program Stream support.
* [1996/10/15 17:30:26 Hans_Graves]
*
* Revision 1.1.6.15 1996/10/12 17:18:51 Hans_Graves
* Fixed some seeking problems. Moved render code to slib_render.c
* [1996/10/12 17:00:49 Hans_Graves]
*
* Revision 1.1.6.14 1996/10/03 19:14:21 Hans_Graves
* Added Presentation and Decoding timestamp support.
* [1996/10/03 19:10:35 Hans_Graves]
*
* Revision 1.1.6.13 1996/09/29 22:19:37 Hans_Graves
* Added stride support. Added SlibQueryData().
* [1996/09/29 21:29:44 Hans_Graves]
*
* Revision 1.1.6.12 1996/09/25 19:16:44 Hans_Graves
* Added DECOMPRESS_QUERY. Fix up support for YUY2.
* [1996/09/25 19:00:45 Hans_Graves]
*
* Revision 1.1.6.11 1996/09/23 18:04:03 Hans_Graves
* Added stats support. Scaleing and negative height fixes.
* [1996/09/23 17:59:31 Hans_Graves]
*
* Revision 1.1.6.10 1996/09/18 23:46:32 Hans_Graves
* Seek fixes. Added SlibReadData() and SlibAddBufferEx().
* [1996/09/18 22:04:57 Hans_Graves]
*
* Revision 1.1.6.9 1996/08/09 20:51:42 Hans_Graves
* Fix handle arg for SlibRegisterVideoBuffer()
* [1996/08/09 20:10:11 Hans_Graves]
*
* Revision 1.1.6.8 1996/07/19 02:11:11 Hans_Graves
* Added SlibRegisterVideoBuffer. Added YUV422i to RGB 16 rendering.
* [1996/07/19 02:01:11 Hans_Graves]
*
* Revision 1.1.6.7 1996/06/03 21:41:12 Hans_Graves
* Fix file seeking. Always seeked to position 0.
* [1996/06/03 21:40:44 Hans_Graves]
*
* Revision 1.1.6.6 1996/05/24 22:21:44 Hans_Graves
* Merge MME-1221. Last SlibReadAudio() returned EndOfStream even if data read.
* [1996/05/24 20:58:42 Hans_Graves]
*
* Revision 1.1.6.5 1996/05/23 18:46:35 Hans_Graves
* Seperate global audio and video SInfo variables, to help multi-threaded apps
* [1996/05/23 18:35:14 Hans_Graves]
*
* Revision 1.1.6.4 1996/05/23 18:16:31 Hans_Graves
* Added more YUV Conversions. MPEG audio buffering fix.
* [1996/05/23 18:16:11 Hans_Graves]
*
* Revision 1.1.6.3 1996/05/10 21:17:00 Hans_Graves
* Added callback support. Also fill entire buffers when calling SlibReadAudio()
* [1996/05/10 20:26:08 Hans_Graves]
*
* Revision 1.1.6.2 1996/05/07 19:56:16 Hans_Graves
* Added SlibOpen() and SlibAddBuffer() framework. Added HUFF_SUPPORT.
* [1996/05/07 17:20:12 Hans_Graves]
*
* Revision 1.1.4.16 1996/05/02 17:10:33 Hans_Graves
* Be more specific about checking for MPEG-2 Systems file type. Fixes MME-01234
* [1996/05/02 17:04:44 Hans_Graves]
*
* Revision 1.1.4.15 1996/04/24 22:33:44 Hans_Graves
* MPEG encoding bitrate fixups.
* [1996/04/24 22:27:09 Hans_Graves]
*
* Revision 1.1.4.14 1996/04/23 21:22:31 Hans_Graves
* Added description for SlibErrorSettingNotEqual
* [1996/04/23 21:16:09 Hans_Graves]
*
* Revision 1.1.4.13 1996/04/22 15:04:51 Hans_Graves
* Fix bad frame counts and seeking under NT caused by int overflows
* [1996/04/22 15:02:26 Hans_Graves]
*
* Revision 1.1.4.12 1996/04/19 21:52:22 Hans_Graves
* MPEG 1 Systems writing enhancements
* [1996/04/19 21:47:48 Hans_Graves]
*
* Revision 1.1.4.11 1996/04/15 14:18:37 Hans_Graves
* Handle any audio buffer size during encoding.
* [1996/04/15 14:16:11 Hans_Graves]
*
* Revision 1.1.4.10 1996/04/12 19:25:20 Hans_Graves
* Add MPEG2_VIDEO type to Commit
* [1996/04/12 19:24:19 Hans_Graves]
*
* Revision 1.1.4.9 1996/04/10 21:47:41 Hans_Graves
* Fix in SlibIsEnd().
* [1996/04/10 21:39:37 Hans_Graves]
*
* Revision 1.1.4.8 1996/04/09 16:04:42 Hans_Graves
* Remove NT warnings
* [1996/04/09 14:42:48 Hans_Graves]
*
* Revision 1.1.4.7 1996/04/04 23:35:07 Hans_Graves
* Format conversion cleanup
* [1996/04/04 23:16:20 Hans_Graves]
*
* Revision 1.1.4.6 1996/04/01 19:07:52 Hans_Graves
* And some error checking
* [1996/04/01 19:04:33 Hans_Graves]
*
* Revision 1.1.4.5 1996/04/01 16:23:12 Hans_Graves
* NT porting
* [1996/04/01 16:15:54 Hans_Graves]
*
* Revision 1.1.4.4 1996/03/29 22:21:30 Hans_Graves
* Added MPEG/JPEG/H261_SUPPORT ifdefs
* [1996/03/29 21:56:55 Hans_Graves]
*
* Added MPEG-I Systems encoding support
* [1996/03/27 21:55:54 Hans_Graves]
*
* Revision 1.1.4.3 1996/03/12 16:15:45 Hans_Graves
* Added seperate streams to SlibIsEnd()
* [1996/03/12 15:56:28 Hans_Graves]
*
* Revision 1.1.4.2 1996/03/08 18:46:42 Hans_Graves
* YUV conversions moved to slibRenderFrame()
* [1996/03/08 18:14:47 Hans_Graves]
*
* Revision 1.1.2.18 1996/02/22 23:30:24 Hans_Graves
* Update FPS on seeks
* [1996/02/22 23:29:27 Hans_Graves]
*
* Revision 1.1.2.17 1996/02/22 22:23:56 Hans_Graves
* Update frame numbers with timecode more often
* [1996/02/22 22:23:07 Hans_Graves]
*
* Revision 1.1.2.16 1996/02/21 22:52:43 Hans_Graves
* Fixed MPEG 2 systems stuff
* [1996/02/21 22:50:55 Hans_Graves]
*
* Revision 1.1.2.15 1996/02/19 20:09:28 Hans_Graves
* Debugging message clean-up
* [1996/02/19 20:08:31 Hans_Graves]
*
* Revision 1.1.2.14 1996/02/19 18:03:54 Hans_Graves
* Fixed a number of MPEG related bugs
* [1996/02/19 17:57:36 Hans_Graves]
*
* Revision 1.1.2.13 1996/02/13 18:47:46 Hans_Graves
* Fix some Seek related bugs
* [1996/02/13 18:40:36 Hans_Graves]
*
* Revision 1.1.2.12 1996/02/07 23:23:54 Hans_Graves
* Added SEEK_EXACT. Fixed most frame counting problems.
* [1996/02/07 23:20:29 Hans_Graves]
*
* Revision 1.1.2.11 1996/02/06 22:54:05 Hans_Graves
* Seek fix-ups. More accurate MPEG frame counts.
* [1996/02/06 22:44:56 Hans_Graves]
*
* Revision 1.1.2.10 1996/02/02 17:36:02 Hans_Graves
* Enhanced audio info. Cleaned up API
* [1996/02/02 17:29:44 Hans_Graves]
*
* Revision 1.1.2.9 1996/01/30 22:23:08 Hans_Graves
* Added AVI YUV support
* [1996/01/30 22:21:38 Hans_Graves]
*
* Revision 1.1.2.8 1996/01/15 16:26:27 Hans_Graves
* Removed debuging message
* [1996/01/15 16:02:47 Hans_Graves]
*
* Added MPEG 1 Audio compression and SlibWriteAudio()
* [1996/01/15 15:45:46 Hans_Graves]
*
* Revision 1.1.2.7 1996/01/11 16:17:29 Hans_Graves
* Added MPEG II Systems decode support
* [1996/01/11 16:12:33 Hans_Graves]
*
* Revision 1.1.2.6 1996/01/08 16:41:31 Hans_Graves
* Added MPEG II decoding support
* [1996/01/08 15:53:02 Hans_Graves]
*
* Revision 1.1.2.5 1995/12/08 20:01:20 Hans_Graves
* Fixed SlibSetParam(). Added H.261 compression support.
* [1995/12/08 19:53:52 Hans_Graves]
*
* Revision 1.1.2.4 1995/12/07 19:31:36 Hans_Graves
* Added JPEG Decoding and MPEG encoding support
* [1995/12/07 18:30:10 Hans_Graves]
*
* Revision 1.1.2.3 1995/11/09 23:14:05 Hans_Graves
* Added MPEG audio decompression
* [1995/11/09 23:08:33 Hans_Graves]
*
* Revision 1.1.2.2 1995/11/06 18:47:52 Hans_Graves
* First time under SLIB
* [1995/11/06 18:36:01 Hans_Graves]
*
* $EndLog$
*/
/*****************************************************************************
** Copyright (c) Digital Equipment Corporation, 1995 **
** **
** All Rights Reserved. Unpublished rights reserved under the copyright **
** laws of the United States. **
** **
** The software contained on this media is proprietary to and embodies **
** the confidential technology of Digital Equipment Corporation. **
** Possession, use, duplication or dissemination of the software and **
** media is authorized only pursuant to a valid written license from **
** Digital Equipment Corporation. **
** **
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
** Government is subject to restrictions as set forth in Subparagraph **
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
******************************************************************************/
/*
#define _SLIBDEBUG_
*/
#include <fcntl.h>
#include <sys/stat.h>
#ifdef WIN32
#include <io.h>
#endif
#ifdef _SHM_
#include <sys/ipc.h> /* shared memory */
#endif
#define SLIB_INTERNAL
#include "slib.h"
#include "SC_err.h"
/* #include "SC_convert.h" */
#include "mpeg.h"
#include "ac3.h"
#include "avi.h"
#ifdef _SLIBDEBUG_
#include <stdio.h>
#include "sc_debug.h"
#define _DEBUG_ 1 /* detailed debuging statements */
#define _VERBOSE_ 1 /* show progress */
#define _VERIFY_ 1 /* verify correct operation */
#define _WARN_ 1 /* warnings about strange behavior */
#define _SEEK_ 1 /* seek, frame counts/timecode info: 2=more detail */
#define _CALLBACK_ 0 /* callback debugging */
#define _DUMP_ 0 /* dump data in hex format */
#define _TIMECODE_ 1 /* debug timecodes */
#endif
static SlibStatus_t slibOpen(SlibHandle_t *handle, SlibMode_t smode,
SlibType_t *stype);
/*
** Lists
*/
static SlibList_t _listTypes [] = {
SLIB_TYPE_MPEG1_VIDEO, "MPEG1_VIDEO", "MPEG-1 Video Stream",0,0,
SLIB_TYPE_MPEG1_AUDIO, "MPEG1_AUDIO", "MPEG-1 Audio Stream",0,0,
SLIB_TYPE_MPEG2_VIDEO, "MPEG2_VIDEO", "MPEG-2 Video Stream",0,0,
SLIB_TYPE_MPEG2_AUDIO, "MPEG2_AUDIO", "MPEG-2 Audio Stream",0,0,
SLIB_TYPE_AC3_AUDIO, "AC3", "Dolby Digital(AC-3) Stream",0,0,
SLIB_TYPE_MPEG_SYSTEMS, "MPEG_SYSTEMS", "MPEG Systems Stream",0,0,
SLIB_TYPE_MPEG_SYSTEMS_MPEG2, "MPEG_SYSTEMS_MPEG2", "MPEG Systems (MPEG-2)",0,0,
SLIB_TYPE_MPEG_TRANSPORT,"MPEG_TRANSPORT", "MPEG Transport Stream",0,0,
SLIB_TYPE_MPEG_PROGRAM, "MPEG_PROGRAM", "MPEG Program Stream",0,0,
SLIB_TYPE_H261, "H261", "H.261 Video Stream",0,0,
SLIB_TYPE_RTP_H261, "RTP_H261", "RTP (H.261) Stream",0,0,
SLIB_TYPE_H263, "H263", "H.263 Video Stream",0,0,
SLIB_TYPE_RTP_H263, "RTP_H263", "RTP (H.263) Stream",0,0,
SLIB_TYPE_RIFF, "RIFF", "RIFF File Format",0,0,
SLIB_TYPE_AVI, "AVI", "AVI File Format",0,0,
SLIB_TYPE_PCM_WAVE, "PCM_WAVE", "WAVE (PCM) File Format",0,0,
SLIB_TYPE_JPEG_AVI, "JPEG_AVI", "AVI (JPEG) Stream",0,0,
SLIB_TYPE_MJPG_AVI, "MJPG_AVI", "AVI (MJPG) Stream",0,0,
SLIB_TYPE_YUV_AVI, "YUV_AVI", "AVI (YUV) File Format",0,0,
SLIB_TYPE_JFIF, "JFIF", "JPEG (JFIF) Stream",0,0,
SLIB_TYPE_JPEG_QUICKTIME,"JPEG_QUICKTIME","JPEG (Quicktime) Stream",0,0,
SLIB_TYPE_JPEG, "JPEG", "JPEG Stream",0,0,
SLIB_TYPE_MJPG, "MJPG", "MJPG Stream",0,0,
SLIB_TYPE_YUV, "YUV", "YUV Data",0,0,
SLIB_TYPE_RGB, "RGB", "RGB Data",0,0,
SLIB_TYPE_PCM, "PCM", "PCM Audio",0,0,
SLIB_TYPE_SLIB, "SLIB", "SLIB Stream",0,0,
SLIB_TYPE_SHUFF, "SHUFF", "SLIB Huffman Stream",0,0,
SLIB_TYPE_G723, "G723", "G.723 Audio Stream",0,0,
SLIB_TYPE_RASTER, "RASTER","Sun Raster",0,0,
SLIB_TYPE_BMP, "BMP", "Windows Bitmap",0,0,
0, NULL, "End of List",0,0
};
static SlibList_t _listCompressTypes [] = {
#ifdef MPEG_SUPPORT
SLIB_TYPE_MPEG1_VIDEO, "MPEG1_VIDEO", "MPEG-1 Video Stream",0,0,
SLIB_TYPE_MPEG1_AUDIO, "MPEG1_AUDIO", "MPEG-1 Audio Stream",0,0,
SLIB_TYPE_MPEG2_VIDEO, "MPEG2_VIDEO", "MPEG-2 Video Stream",0,0,
SLIB_TYPE_MPEG_SYSTEMS, "MPEG_SYSTEMS", "MPEG Systems Stream",0,0,
SLIB_TYPE_MPEG_SYSTEMS_MPEG2, "MPEG2_SYSTEMS", "MPEG Systems (MPEG-2)",0,0,
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
SLIB_TYPE_H261, "H261", "H.261 Video Stream",0,0,
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
SLIB_TYPE_H263, "H263", "H.263 Video Stream",0,0,
#endif /* H263_SUPPORT */
#ifdef HUFF_SUPPORT
SLIB_TYPE_SHUFF, "SHUFF", "SLIB Huffman Stream",0,0,
#endif /* HUFF_SUPPORT */
#ifdef G723_SUPPORT
SLIB_TYPE_G723, "G723", "G.723 Audio Stream",0,0,
#endif /* G723_SUPPORT */
0, NULL, "End of List",0,0
};
static SlibList_t _listDecompressTypes [] = {
#ifdef MPEG_SUPPORT
SLIB_TYPE_MPEG1_VIDEO, "MPEG1_VIDEO", "MPEG-1 Video Stream",0,0,
SLIB_TYPE_MPEG1_AUDIO, "MPEG1_AUDIO", "MPEG-1 Audio Stream",0,0,
SLIB_TYPE_MPEG2_VIDEO, "MPEG2_VIDEO", "MPEG-2 Video Stream",0,0,
SLIB_TYPE_MPEG_SYSTEMS, "MPEG_SYSTEMS", "MPEG Systems Stream",0,0,
SLIB_TYPE_MPEG_SYSTEMS_MPEG2, "MPEG2_SYSTEMS", "MPEG Systems (MPEG-2)",0,0,
SLIB_TYPE_MPEG_TRANSPORT, "MPEG_TRANSPORT", "MPEG Transport Stream",0,0,
SLIB_TYPE_MPEG_PROGRAM, "MPEG_PROGRAM", "MPEG Program Stream",0,0,
#endif /* MPEG_SUPPORT */
#ifdef AC3_SUPPORT
SLIB_TYPE_AC3_AUDIO, "AC3", "Dolby Digital(AC-3) Stream",0,0,
#endif /* AC3_SUPPORT */
#ifdef H261_SUPPORT
SLIB_TYPE_H261, "H261", "H.261 Video Stream",0,0,
SLIB_TYPE_RTP_H261, "RTP_H261", "RTP (H.261) Stream",0,0,
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
SLIB_TYPE_H263, "H263", "H.263 Video Stream",0,0,
SLIB_TYPE_RTP_H263, "RTP_H263", "RTP (H.263) Stream",0,0,
#endif /* H261_SUPPORT */
#ifdef JPEG_SUPPORT
SLIB_TYPE_JPEG_AVI, "JPEG_AVI", "AVI (JPEG) Stream",0,0,
SLIB_TYPE_MJPG_AVI, "MJPG_AVI", "AVI (MJPG) Stream",0,0,
#endif /* JPEG_SUPPORT */
SLIB_TYPE_RIFF, "RIFF", "RIFF File Format",0,0,
SLIB_TYPE_AVI, "AVI", "AVI File Format",0,0,
SLIB_TYPE_PCM_WAVE, "PCM_WAVE", "WAVE (PCM) File Format",0,0,
SLIB_TYPE_YUV_AVI, "YUV_AVI", "AVI (YUV) File Format",0,0,
SLIB_TYPE_RASTER, "RASTER","Sun Raster",0,0,
SLIB_TYPE_BMP, "BMP", "Windows Bitmap",0,0,
#ifdef HUFF_SUPPORT
SLIB_TYPE_SHUFF, "SHUFF", "SLIB Huffman Stream",0,0,
#endif /* HUFF_SUPPORT */
#ifdef G723_SUPPORT
SLIB_TYPE_G723, "G723", "G.723 Audio Stream",0,0,
#endif /* G723_SUPPORT */
0, NULL, "End of List",0,0
};
static SlibList_t _listErrors[] = {
SlibErrorNone, "SlibErrorNone",
"No Error",0,0,
SlibErrorInternal, "SlibErrorInternal",
"Internal SLIB error",0,0,
SlibErrorMemory, "SlibErrorMemory",
"Unable to allocated memory",0,0,
SlibErrorBadArgument, "SlibErrorBadArgument",
"Invalid argument to function",0,0,
SlibErrorBadHandle, "SlibErrorBadHandle",
"Invalid SLIB handle",0,0,
SlibErrorBadMode, "SlibErrorBadMode",
"Invalid SLIB mode",0,0,
SlibErrorUnsupportedFormat, "SlibErrorUnsupportedFormat",
"Unsupported format",0,0,
SlibErrorReading, "SlibErrorReading",
"Error reading from file",0,0,
SlibErrorWriting, "SlibErrorWriting",
"Error writing to file",0,0,
SlibErrorBufSize, "SlibErrorBufSize",
"Buffer size is too small",0,0,
SlibErrorEndOfStream, "SlibErrorEndOfStream",
"End of data stream",0,0,
SlibErrorForwardOnly, "SlibErrorForwardOnly",
"The decompressor can work only forward",0,0,
SlibErrorUnsupportedParam, "SlibErrorUnsupportedParam",
"The parameter is invalid or unsupported",0,0,
SlibErrorImageSize, "SlibErrorImageSize",
"Invalid image height and/or width size",0,0,
SlibErrorSettingNotEqual, "SlibErrorSettingNotEqual",
"The exact parameter setting was not used",0,0,
SlibErrorInit, "SlibErrorInit",
"Initializing CODEC failed",0,0,
SlibErrorFileSize, "SlibErrorFileSize",
"Error in file size",0,0,
SlibErrorBadPosition, "SlibErrorBadPosition",
"Error in seek position",0,0,
SlibErrorBadUnit, "SlibErrorBadUnit",
"Error in seek units",0,0,
SlibErrorNoData, "SlibErrorNoData",
"No data available",0,0,
0, NULL, "End of List",0,0
};
SlibList_t *SlibFindEnumEntry(SlibList_t *list, int enumval)
{
if (!list)
return(NULL);
while (list->Name)
{
if (list->Enum==enumval)
return(list);
list++;
}
return(NULL);
}
char *SlibGetErrorText(SlibStatus_t status)
{
SlibList_t *entry=SlibFindEnumEntry(_listErrors, status);
if (entry)
return(entry->Desc);
else
return(NULL);
}
int VCompressCallback(SvHandle_t Svh, SvCallbackInfo_t *CB,
SvPictureInfo_t *pinfo)
{
int status;
SlibInfo_t *Info=(SlibInfo_t *)CB->UserData;
_SlibDebug(_CALLBACK_, printf("VCompressCallback()\n") );
switch (CB->Message)
{
case CB_END_BUFFERS:
_SlibDebug(_CALLBACK_,
printf("VCompressCallback received CB_END_BUFFER message\n") );
if (CB->DataType==CB_DATA_COMPRESSED)
{
CB->DataSize=Info->CompBufSize;
CB->Data=SlibAllocBuffer(CB->DataSize);
status=SvAddBuffer(Svh, CB);
_SlibDebug(_WARN_ && status!=NoErrors,
printf("SvAddBuffer() %s\n", ScGetErrorStr(status)) );
}
break;
case CB_RELEASE_BUFFER:
_SlibDebug(_CALLBACK_,
printf("VCompressCallback received CB_RELEASE_BUFFER message\n"));
if (CB->DataType==CB_DATA_COMPRESSED && CB->Data && CB->DataUsed)
{
SlibPin_t *dstpin=slibGetPin(Info, SLIB_DATA_VIDEO);
if (dstpin)
{
slibAddBufferToPin(dstpin, CB->Data, CB->DataUsed,
Info->VideoPTimeCode);
Info->VideoPTimeCode=SLIB_TIME_NONE;
if (!slibCommitBuffers(Info, FALSE))
CB->Action = CB_ACTION_END;
break;
}
}
if (CB->Data)
SlibFreeBuffer(CB->Data);
break;
case CB_FRAME_START:
_SlibDebug(_CALLBACK_||_TIMECODE_,
printf("VCompress CB_FRAME_START: TimeCode=%ld TemporalRef=%d\n",
pinfo->TimeCode, pinfo->TemporalRef) );
Info->VideoPTimeCode=pinfo->TimeCode;
#if 0
if (pinfo->Type==SV_I_PICTURE || pinfo->Type==SV_P_PICTURE)
{
if (!SlibTimeIsValid(Info->LastVideoDTimeCode))
Info->VideoDTimeCode=-1000/(long)Info->FramesPerSec;
else
Info->VideoDTimeCode=Info->LastVideoDTimeCode;
Info->LastVideoDTimeCode=pinfo->TimeCode;
_SlibDebug(_CALLBACK_||_TIMECODE_,
printf("CB_FRAME_START: LastVideoDTimeCode=%ld VideoDTimeCode=%ld\n",
Info->LastVideoDTimeCode, Info->VideoDTimeCode));
}
else
Info->VideoDTimeCode=-1;
#endif
break;
}
CB->Action = CB_ACTION_CONTINUE;
return(NoErrors);
}
int VDecompressCallback(SvHandle_t Svh, SvCallbackInfo_t *CB,
SvPictureInfo_t *PictInfo)
{
int status;
unsigned dword size;
SlibInfo_t *Info=(SlibInfo_t *)CB->UserData;
_SlibDebug(_CALLBACK_, printf("VDecompressCallback()\n") );
switch (CB->Message)
{
case CB_SEQ_END: /* reset presentation timestamps at end-of-sequence */
_SlibDebug(_CALLBACK_ || _TIMECODE_,
printf("VDecompressCallback received CB_SEQ_END message\n") );
Info->VideoPTimeCode=SLIB_TIME_NONE;
Info->AudioPTimeCode=SLIB_TIME_NONE;
Info->VideoTimeStamp=SLIB_TIME_NONE;
Info->AudioTimeStamp=SLIB_TIME_NONE;
break;
case CB_END_BUFFERS:
_SlibDebug(_CALLBACK_,
printf("VDecompressCallback received CB_END_BUFFER message\n") );
if (CB->DataType==CB_DATA_COMPRESSED)
{
SlibTime_t ptimestamp, timediff;
slibSetMaxInput(Info, 1500*1024); /* set limit for input data */
CB->Data = SlibGetBuffer(Info, SLIB_DATA_VIDEO, &size,
&ptimestamp);
slibSetMaxInput(Info, 0); /* clear limit */
CB->DataSize = size;
if (SlibTimeIsValid(Info->AudioPTimeCode))
{
timediff=ptimestamp-Info->AudioPTimeCode;
if (timediff>6000)
{
/* Make sure a NEW audio time is not way out of
* sync with video time.
* This can happen after an End of Sequence.
*/
/* assign audio time to video time */
Info->VideoPTimeCode=SLIB_TIME_NONE;
Info->VideoPTimeBase=Info->AudioPTimeBase;
ptimestamp=Info->AudioPTimeCode;
}
}
if (SlibTimeIsValid(ptimestamp) &&
ptimestamp>Info->VideoPTimeCode)
{
SlibTime_t lasttime=Info->VideoPTimeCode;
Info->VideoPTimeCode=ptimestamp;
_SlibDebug(_CALLBACK_||_TIMECODE_,
printf("VideoPTimeCode=%ld\n", Info->VideoPTimeCode) );
ptimestamp-=Info->VideoPTimeBase;
timediff=ptimestamp-Info->VideoTimeStamp;
if (SlibTimeIsInValid(lasttime) ||
SlibTimeIsInValid(Info->VideoTimeStamp))
{
_SlibDebug(_TIMECODE_,
printf("Updating VideoTimeStamp none->%ld\n",
ptimestamp) );
Info->VideoTimeStamp=ptimestamp;
Info->AvgVideoTimeDiff=0;
Info->VarVideoTimeDiff=0;
}
else /* see if times are far off */
{
SlibTime_t lastavg=Info->AvgVideoTimeDiff;
Info->AvgVideoTimeDiff=(lastavg*14+timediff)/15;
Info->VarVideoTimeDiff=(Info->VarVideoTimeDiff*3+
lastavg-Info->AvgVideoTimeDiff)/4;
_SlibDebug(_CALLBACK_||_TIMECODE_,
printf("Video timediff: Cur=%ld Avg=%ld Var=%ld\n",
timediff, Info->AvgVideoTimeDiff,
Info->VarVideoTimeDiff));
if (Info->VarVideoTimeDiff==0)
{
_SlibDebug(_TIMECODE_,
printf("Updating VideoTimeStamp %ld->%ld (diff=%ld)\n",
Info->VideoTimeStamp, ptimestamp,
ptimestamp-Info->VideoTimeStamp) );
Info->VideoTimeStamp=ptimestamp;
Info->AvgVideoTimeDiff=0;
}
else if (Info->AvgVideoTimeDiff>=100
|| Info->AvgVideoTimeDiff<=-100)
{
/* calculated time and timestamps are too far off */
float fps=Info->FramesPerSec;
if (Info->VarVideoTimeDiff>1 && fps>=15.5F)
fps-=0.25F; /* playing too fast, slow frame rate */
else if (Info->VarVideoTimeDiff<-1 && fps<=59.0F)
fps+=0.25F; /* playing too slow, speed up frame rate */
_SlibDebug(_WARN_ || _CALLBACK_||_TIMECODE_,
printf("Updating fps from %.4f -> %.4f\n",
Info->FramesPerSec, fps) );
Info->FramesPerSec=fps;
Info->VideoFrameDuration=slibFrameToTime100(Info, 1);
Info->VideoTimeStamp=ptimestamp;
Info->AvgVideoTimeDiff=0;
}
}
Info->VideoFramesProcessed=0; /* reset frames processed */
}
if (CB->DataSize>0)
{
_SlibDebug(_DUMP_,
SlibPin_t *pin=slibGetPin(Info, SLIB_DATA_VIDEO);
printf("VDecompressCallback() Adding buffer of length %d\n",
CB->DataSize);
ScDumpChar(CB->Data, (int)CB->DataSize, (int)pin->Offset-CB->DataSize));
CB->DataType = CB_DATA_COMPRESSED;
_SlibDebug(_CALLBACK_,
printf("VDecompressCallback() Adding buffer of length %d\n",
CB->DataSize) );
status = SvAddBuffer(Svh, CB);
}
else
{
_SlibDebug(_WARN_ || _CALLBACK_,
printf("VDecompressCallback() got no data\n") );
CB->Action = CB_ACTION_END;
return(NoErrors);
}
}
break;
case CB_RELEASE_BUFFER:
_SlibDebug(_CALLBACK_,
printf("VDecompressCallback received CB_RELEASE_BUFFER message\n"));
if (CB->DataType==CB_DATA_COMPRESSED && CB->Data)
SlibFreeBuffer(CB->Data);
break;
case CB_PROCESSING:
_SlibDebug(_CALLBACK_,
printf("VDecompressCallback received CB_PROCESSING message\n") );
break;
case CB_CODEC_DONE:
_SlibDebug(_CALLBACK_,
printf("VDecompressCallback received CB_CODEC_DONE message\n") );
break;
}
CB->Action = CB_ACTION_CONTINUE;
return(NoErrors);
}
int ACompressCallback(SaHandle_t Sah, SaCallbackInfo_t *CB, SaInfo_t *SaInfo)
{
int status;
SlibInfo_t *Info=(SlibInfo_t *)CB->UserData;
_SlibDebug(_CALLBACK_, printf("ACompressCallback()\n") );
CB->Action = CB_ACTION_CONTINUE;
switch (CB->Message)
{
case CB_END_BUFFERS:
_SlibDebug(_CALLBACK_,
printf("ACompressCallback received CB_END_BUFFER message\n") );
if (CB->DataType==CB_DATA_COMPRESSED)
{
CB->DataSize=Info->CompBufSize;
CB->Data=SlibAllocBuffer(CB->DataSize);
_SlibDebug(_CALLBACK_,
printf("ACompressCallback() Adding buffer of length %d\n",
CB->DataSize) );
status=SaAddBuffer(Sah, CB);
_SlibDebug(_WARN_ && status!=NoErrors,
printf("SaAddBuffer() %s\n", ScGetErrorStr(status)) );
}
break;
case CB_RELEASE_BUFFER:
_SlibDebug(_CALLBACK_,
printf("ACompressCallback received CB_RELEASE_BUFFER message\n"));
if (CB->DataType==CB_DATA_COMPRESSED && CB->Data && CB->DataUsed)
{
SlibPin_t *dstpin=slibGetPin(Info, SLIB_DATA_AUDIO);
if (dstpin)
{
slibAddBufferToPin(dstpin, CB->Data, CB->DataUsed,
Info->AudioPTimeCode);
Info->AudioPTimeCode=SLIB_TIME_NONE;
if (!slibCommitBuffers(Info, FALSE))
CB->Action = CB_ACTION_END;
}
}
else if (CB->Data)
SlibFreeBuffer(CB->Data);
break;
case CB_FRAME_START:
_SlibDebug(_CALLBACK_||_TIMECODE_,
printf("ACompress CB_FRAME_START: TimeStamp=%ld Frame=%d\n",
CB->TimeStamp, Info->VideoFramesProcessed
) );
if (SlibTimeIsInValid(Info->AudioPTimeCode))
{
Info->AudioPTimeCode=CB->TimeStamp;
_SlibDebug(_TIMECODE_,
printf("AudioPTimeCode=%ld\n", Info->AudioPTimeCode) );
_SlibDebug(_WARN_ && (Info->AudioTimeStamp-CB->TimeStamp>400 ||
CB->TimeStamp-Info->AudioTimeStamp>400),
printf("Bad Audio Time: AudioPTimeCode=%ld AudioTimestamp=%ld\n",
Info->AudioPTimeCode, Info->AudioTimeStamp) );
}
break;
}
return(NoErrors);
}
int ADecompressCallback(SvHandle_t Sah, SaCallbackInfo_t *CB, SaInfo_t *SaInfo)
{
int status;
unsigned dword size;
SlibInfo_t *Info=(SlibInfo_t *)CB->UserData;
_SlibDebug(_DEBUG_, printf("ADecompressCallback()\n") );
switch (CB->Message)
{
case CB_END_BUFFERS:
_SlibDebug(_CALLBACK_,
printf("ADecompressCallback() CB_END_BUFFER\n") );
if (CB->DataType==CB_DATA_COMPRESSED)
{
SlibTime_t ptimestamp, timediff;
slibSetMaxInput(Info, 2000*1024); /* set limit for input data */
CB->Data = SlibGetBuffer(Info, SLIB_DATA_AUDIO, &size,
&ptimestamp);
slibSetMaxInput(Info, 0); /* clear limit */
CB->DataSize = size;
if (SlibTimeIsValid(ptimestamp))
{
Info->AudioPTimeCode=ptimestamp;
_SlibDebug(_CALLBACK_||_TIMECODE_,
printf("AudioPTimeCode=%ld\n", Info->AudioPTimeCode) );
ptimestamp-=Info->AudioPTimeBase;
timediff=ptimestamp-Info->AudioTimeStamp;
if (SlibTimeIsInValid(Info->AudioTimeStamp))
Info->AudioTimeStamp=ptimestamp;
else if (timediff<-300 || timediff>300) /* time is far off */
{
_SlibDebug(_WARN_||_TIMECODE_,
printf("Updating AudioTimeStamp %ld->%ld (diff=%ld)\n",
Info->AudioTimeStamp, ptimestamp,timediff) );
Info->AudioTimeStamp=ptimestamp;
if (SlibTimeIsValid(Info->VideoTimeStamp))
{
/* Make sure a NEW audio time is not way out of
* sync with video time.
* This can happen after an End of Sequence.
*/
timediff=ptimestamp-Info->VideoTimeStamp;
if (timediff<-6000)
{
/* assign audio time to video time */
Info->VideoPTimeCode=SLIB_TIME_NONE;
Info->VideoPTimeBase=Info->AudioPTimeBase;
Info->VideoTimeStamp=ptimestamp;
}
}
}
}
if (CB->Data)
{
if (CB->DataSize>0)
{
CB->DataType = CB_DATA_COMPRESSED;
_SlibDebug(_CALLBACK_,
printf("ADecompressCallback() Adding buffer of length %d\n",
CB->DataSize) );
status = SaAddBuffer(Sah, CB);
}
else
SlibFreeBuffer(CB->Data);
}
else
{
_SlibDebug(_WARN_ || _CALLBACK_,
printf("ADecompressCallback() got no data\n") );
CB->Action = CB_ACTION_END;
return(NoErrors);
}
}
break;
case CB_RELEASE_BUFFER:
_SlibDebug(_CALLBACK_,
printf("ADecompressCallback() CB_RELEASE_BUFFER\n"));
if (CB->DataType==CB_DATA_COMPRESSED && CB->Data)
SlibFreeBuffer(CB->Data);
break;
case CB_PROCESSING:
_SlibDebug(_CALLBACK_,
printf("ADecompressCallback() CB_PROCESSING\n") );
break;
case CB_CODEC_DONE:
_SlibDebug(_CALLBACK_,
printf("ADecompressCallback() CB_CODEC_DONE\n") );
break;
}
CB->Action = CB_ACTION_CONTINUE;
return(NoErrors);
}
static void slibInitInfo(SlibInfo_t *Info)
{
_SlibDebug(_DEBUG_, printf("slibInitInfo()\n") );
Info->Type = SLIB_TYPE_UNKNOWN;
Info->Mode = SLIB_MODE_NONE;
Info->Svh = NULL;
Info->Sah = NULL;
Info->Sch = NULL;
Info->NeedAccuracy = FALSE;
Info->TotalBitRate = 0;
Info->MuxBitRate = 0;
Info->SystemTimeStamp = 0;
/* Audio parameters */
Info->AudioStreams = 0;
Info->SamplesPerSec = 0;
Info->BitsPerSample = 0;
Info->Channels = 0;
Info->AudioBitRate = 0;
Info->AudioMainStream = 0;
Info->AudioType = SLIB_TYPE_UNKNOWN;
/* Video parameters */
Info->VideoStreams = 0;
Info->Width = 0;
Info->Height = 0;
Info->Stride = 0;
Info->VideoBitRate = 0;
Info->FramesPerSec = 0.0F;
Info->ImageSize = 0;
Info->AudioPID = -1;
Info->VideoPID = -1;
Info->VideoMainStream = 0;
Info->VideoType = SLIB_TYPE_UNKNOWN;
/* Data Exchange */
Info->Offset = 0;
Info->Pins = NULL;
Info->PinCount = 0;
Info->IOError = FALSE;
Info->MaxBytesInput = 0;
Info->BytesProcessed = 0;
/* stream dependent stuff */
Info->VideoLength = 0;
Info->VideoLengthKnown = FALSE;
Info->VideoTimeStamp = SLIB_TIME_NONE;
Info->VideoFrameDuration = 0;
Info->AudioLength = 0;
Info->AudioLengthKnown = FALSE;
Info->AudioTimeStamp = SLIB_TIME_NONE;
Info->LastAudioTimeStamp = SLIB_TIME_NONE;
Info->KeySpacing = 0;
Info->SubKeySpacing = 0;
Info->VideoPTimeBase = SLIB_TIME_NONE;
Info->VideoPTimeCode = SLIB_TIME_NONE;
Info->VideoDTimeCode = SLIB_TIME_NONE;
Info->LastAudioPTimeCode = SLIB_TIME_NONE;
Info->LastVideoPTimeCode = SLIB_TIME_NONE;
Info->LastVideoDTimeCode = SLIB_TIME_NONE;
Info->AvgVideoTimeDiff = 0;
Info->VarVideoTimeDiff = 0;
Info->AudioPTimeBase = SLIB_TIME_NONE;
Info->AudioPTimeCode = SLIB_TIME_NONE;
Info->AudioDTimeCode = SLIB_TIME_NONE;
Info->VideoFramesProcessed=0;
/* Encoding info */
Info->HeaderProcessed = FALSE;
Info->PacketCount = 0;
Info->BytesSincePack = 0;
/* Miscellaneous */
Info->SlibCB = NULL;
Info->SlibCBUserData = NULL;
Info->Fd = -1;
Info->FileSize = 0;
Info->FileBufSize = 50*1024;
Info->CompBufSize = 2*1024;
Info->PacketSize = 512;
Info->AudioFormat = NULL;
Info->VideoFormat = NULL;
Info->CompAudioFormat = NULL;
Info->CompVideoFormat = NULL;
Info->CodecVideoFormat = NULL;
Info->VideoCodecState = SLIB_CODEC_STATE_NONE;
Info->AudioCodecState = SLIB_CODEC_STATE_NONE;
Info->Imagebuf = NULL;
Info->IntImagebuf = NULL;
Info->IntImageSize = 0;
Info->CodecImagebuf = NULL;
Info->CodecImageSize = 0;
Info->Multibuf = NULL;
Info->MultibufSize = 0;
Info->Audiobuf = NULL;
Info->AudiobufSize = 0;
Info->AudiobufUsed = 0;
Info->OverflowSize = 1500*1024;
Info->VBVbufSize = 0;
Info->stats = NULL;
Info->dbg = NULL;
}
/*
** Name: slibGetDataFormat
** Purpose: Find out the type of some multmedia data.
*/
static SlibType_t slibGetDataFormat(unsigned char *buf, int size,
dword *headerstart,
dword *headersize)
{
dword i, count;
unsigned char *bufptr;
if (headersize)
*headersize=0;
if (size<4 || !buf)
return(SLIB_TYPE_UNKNOWN);
/*
** H261 video stream file
*/
if ((buf[0] == 0x00) &&
(buf[1] == 0x01) &&
(buf[2] & 0xF0)==0x00)
return(SLIB_TYPE_H261);
/*
** H263 video stream file
*/
if ((buf[0] == 0x00) &&
(buf[1] == 0x00) &&
(buf[2] == 0x80) &&
(buf[3] & 0xF8)==0x00)
return(SLIB_TYPE_H263);
/*
** JFIF file (ffd8 = Start-Of-Image marker)
*/
if (buf[0] == 0xff && buf[1] == 0xd8)
return(SLIB_TYPE_JFIF);
/*
** QUICKTIME JPEG file (4 ignored bytes, "mdat", ff, d8, ff)
*/
if ((strncmp(&buf[4], "mdat", 4) == 0 ) &&
(buf[8] == 0xff) &&
(buf[9] == 0xd8) &&
(buf[10] == 0xff))
return(SLIB_TYPE_JPEG_QUICKTIME);
/*
** AVI RIFF file
*/
if ( strncmp(buf, "RIFF", 4) == 0 )
{
if (strncmp(&buf[8], "WAVE",4) == 0)
return(SLIB_TYPE_PCM_WAVE);
else if (strncmp(&buf[8], "AVI ",4) == 0)
return(SLIB_TYPE_AVI);
else
return(SLIB_TYPE_RIFF);
}
/*
** BMP file
*/
if (buf[0] == 'B' && buf[1]=='M')
return(SLIB_TYPE_BMP);
/*
** Dolby AC-3 stream
*/
if ((buf[0]==0x77 && buf[1] == 0x0B) || /* may be byte reversed */
(buf[0]==0x0B && buf[1] == 0x77))
return(SLIB_TYPE_AC3_AUDIO);
/*
** Sun Raster file
*/
if ((buf[0]==0x59 && buf[1] == 0xA6) || /* may be byte reversed */
(buf[0]==0x6A && buf[1] == 0x95))
return(SLIB_TYPE_RASTER);
/*
** SLIB file
*/
if ((buf[0] == 'S') && (buf[1] == 'L') &&
(buf[2] == 'I') && (buf[3] == 'B'))
{
if ((buf[4] == 'H') && (buf[5] == 'U') && /* SLIB Huffman Stream */
(buf[6] == 'F') && (buf[7] == 'F'))
return(SLIB_TYPE_SHUFF);
else
return(SLIB_TYPE_SLIB);
}
/*
** MPEG II Transport Stream
*/
if (buf[0] == MPEG_TSYNC_CODE &&
(buf[3]&0x30)!=0) /* adaptation field value is not reserved */
return(SLIB_TYPE_MPEG_TRANSPORT);
if (buf[0] == MPEG_TSYNC_CODE && buf[1] == 0x1F &&
buf[2]==0xFF) /* NULL PID */
return(SLIB_TYPE_MPEG_TRANSPORT);
/* search for mpeg startcode 000001 */
bufptr=buf;
for (i=4, count=size;
i<count && (bufptr[0]!=0x00 || bufptr[1]!=0x00 || bufptr[2]!=0x01); i++)
bufptr++;
count-=i-4;
if (headerstart)
*headerstart=i-4;
/*
** MPEG video file
*/
if (bufptr[0] == 0x00 && bufptr[1] == 0x00 &&
bufptr[2] == 0x01 && bufptr[3] == 0xB3)
{
if (headersize) /* calculate the header size */
{
*headersize=12; /* minimum size is twelve bytes */
if (count>11 && (bufptr[11]&0x02)) /* load_intra_quantizer_matrixe */
{
*headersize+=64;
if (count>75 && bufptr[64+11]&0x01) /* load_non_intra_quantizer_matrix */
*headersize+=64;
}
else if (count>11 && (bufptr[11]&0x01)) /* load_non_intra_quant_matrix */
*headersize+=64;
}
return(SLIB_TYPE_MPEG1_VIDEO);
}
/*
** MPEG I Systems file
*/
if ((bufptr[0] == 0x00) && (bufptr[1] == 0x00) &&
(bufptr[2] == 0x01) && (bufptr[3] == 0xba) &&
((bufptr[4]&0xF0) == 0x20))
return(SLIB_TYPE_MPEG_SYSTEMS);
/*
** MPEG II Program Stream
*/
if ((bufptr[0] == 0x00) && (bufptr[1] == 0x00) &&
(bufptr[2] == 0x01) && (bufptr[3] == 0xba) &&
((bufptr[4]&0xC0) == 0x40))
return(SLIB_TYPE_MPEG_PROGRAM);
/*
** H263 video stream file
*/
/* search for H.263 picture startcode 000000000000000100000 */
for (bufptr=buf, i=0, count=size-4; i<count; i++, bufptr++)
{
if ((bufptr[0] == 0x00) &&
(bufptr[1] == 0x00) &&
(bufptr[2] == 0x80) &&
(bufptr[3] & 0xF8)==0x00)
return(i>=12 ? SLIB_TYPE_RTP_H263 : SLIB_TYPE_H263);
}
/*
** H261 video stream file
*/
/* search for H.261 picture startcode 00000000000000010000 */
for (bufptr=buf, i=0, count=size-3; i<count; i++, bufptr++)
{
if ((bufptr[0] == 0x00) &&
(bufptr[1] == 0x01) &&
(bufptr[2] & 0xF0)==0x00)
return(i>=12 ? SLIB_TYPE_RTP_H261 : SLIB_TYPE_H261);
}
/*
** MPEG audio stream file
*/
if (buf[0]==0xFF && (buf[1] & 0xF0)==0xF0)
return(SLIB_TYPE_MPEG1_AUDIO);
#ifdef G723_SUPPORT
//Detect the RATEFLAG and VADFLAG in each frame in this
//buffer.
{
int i,iFrameSize,iNoOfFrames;
BOOL bRateFlag; //0 for High rate(6.3K 24bit), 1 for low rate(5.3K,20bit)
BOOL bVADflag; // 0 for Active speech 1 for Non-speech
BOOL bTypeG723 = TRUE; //Initialized to say that it's a g723 media stream
if(buf[0] & 0x1)
{
bRateFlag = TRUE; //Low rate 5.3K
iFrameSize = 20;
}
else
{
bRateFlag = FALSE; //High Rate 6.3K
iFrameSize = 24;
}
if(buf[0] & 0x2)
bVADflag =TRUE; //Non-Speech
else
bVADflag = FALSE; //Active-Speech
iNoOfFrames = size/iFrameSize;
if (iNoOfFrames>15) iNoOfFrames=15; /* just check first 15 frames */
//Leave the first frame.The first frame is used to extract
// the above information.Check for this info in the remaining
// frames.If it exists in all frames,the audio is G723 ,otherwise
// audio type is Unknown.
for(i =1; i < iNoOfFrames;i++)
{
//Search for RateFlag and bVADflag for each frame
if(((buf[i*iFrameSize] & 0x1) == bRateFlag) &&
((buf[i*iFrameSize] & 0x2) == bVADflag))
continue;
//type is Unknown ,Set the flag to false and
//break from the for loop
bTypeG723 = FALSE;
break;
}
if(bTypeG723)
return(SLIB_TYPE_G723);
}
#endif /* G723_SUPPORT */
_SlibDebug(_WARN_, printf("slibGetDataFormat() Unknown file format\n") );
return(SLIB_TYPE_UNKNOWN);
}
SlibStatus_t SlibQueryData(void *databuf, unsigned dword databufsize,
SlibQueryInfo_t *qinfo)
{
SlibInfo_t *Info=NULL;
SlibStatus_t status;
if (!databuf)
return(SlibErrorBadArgument);
if (databufsize==0)
return(SlibErrorBufSize);
qinfo->Bitrate=0;
qinfo->VideoStreams=0;
qinfo->Width=0;
qinfo->Height=0;
qinfo->VideoBitrate=0;
qinfo->FramesPerSec=0.0F;
qinfo->VideoLength=0;
qinfo->AudioStreams=0;
qinfo->SamplesPerSec=0;
qinfo->BitsPerSample=0;
qinfo->Channels=0;
qinfo->AudioBitrate=0;
qinfo->AudioLength=0;
qinfo->Type = slibGetDataFormat(databuf, databufsize,
&qinfo->HeaderStart, &qinfo->HeaderSize);
if (qinfo->Type!=SLIB_TYPE_UNKNOWN)
{
if ((Info = (SlibInfo_t *)ScAlloc(sizeof(SlibInfo_t))) == NULL)
return(SlibErrorMemory);
slibInitInfo(Info);
Info->Mode = SLIB_MODE_DECOMPRESS;
Info->Type = qinfo->Type;
slibAddPin(Info, SLIB_DATA_COMPRESSED, "Compressed");
status=slibManageUserBuffer(NULL, databuf, databufsize, NULL);
if (status==SlibErrorNone)
status=slibAddBufferToPin(slibGetPin(Info, SLIB_DATA_COMPRESSED),
databuf, databufsize, SLIB_TIME_NONE);
if (status!=SlibErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(status);
}
slibAddPin(Info, SLIB_DATA_AUDIO, "Audio");
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
SlibUpdateAudioInfo(Info);
SlibUpdateVideoInfo(Info);
if (Info->TotalBitRate==0)
qinfo->Bitrate=Info->AudioBitRate+
((Info->VideoBitRate>100000000)?0:Info->VideoBitRate);
else
qinfo->Bitrate=Info->TotalBitRate;
qinfo->VideoStreams=Info->VideoStreams;
qinfo->Width=Info->Width;
qinfo->Height=Info->Height;
qinfo->VideoBitrate=Info->VideoBitRate;
qinfo->FramesPerSec=Info->FramesPerSec;
qinfo->VideoLength=Info->VideoLength;
qinfo->AudioStreams=Info->AudioStreams;
qinfo->SamplesPerSec=Info->SamplesPerSec;
qinfo->BitsPerSample=Info->BitsPerSample;
qinfo->Channels=Info->Channels;
qinfo->AudioBitrate=Info->AudioBitRate;
qinfo->AudioLength=Info->AudioLength;
SlibClose((SlibHandle_t)Info);
return(SlibErrorNone);
}
return(SlibErrorUnsupportedFormat);
}
/************************** The Main Slib API ***********************/
SlibStatus_t SlibOpen(SlibHandle_t *handle, SlibMode_t smode,
SlibType_t *stype, SlibMessage_t (*slibCB)(SlibHandle_t,
SlibMessage_t, SlibCBParam1_t, SlibCBParam2_t, void *),
void *cbuserdata)
{
SlibInfo_t *Info=NULL;
SlibStatus_t status;
_SlibDebug(_VERBOSE_,printf("SlibOpen()\n") );
if (!handle)
return(SlibErrorBadHandle);
*handle = NULL;
if (!stype)
return(SlibErrorBadArgument);
if (!slibCB)
return(SlibErrorBadArgument);
if (smode == SLIB_MODE_COMPRESS)
{
if (SlibFindEnumEntry(_listCompressTypes, *stype)==NULL)
return(SlibErrorUnsupportedFormat);
}
if ((Info = (SlibInfo_t *)ScAlloc(sizeof(SlibInfo_t))) == NULL)
return(SlibErrorMemory);
slibInitInfo(Info);
slibAddPin(Info, SLIB_DATA_COMPRESSED, "Compressed");
Info->SlibCB = slibCB;
Info->SlibCBUserData = cbuserdata;
*handle=(SlibHandle_t)Info;
if ((status=slibOpen(handle, smode, stype))!=SlibErrorNone)
*handle = NULL;
return(status);
}
SlibStatus_t SlibOpenSync(SlibHandle_t *handle, SlibMode_t smode,
SlibType_t *stype, void *buffer, unsigned dword bufsize)
{
SlibInfo_t *Info=NULL;
SlibStatus_t status;
_SlibDebug(_VERBOSE_,printf("SlibOpenSync()\n") );
if (!handle)
return(SlibErrorBadHandle);
*handle = NULL;
if (!stype)
return(SlibErrorBadArgument);
if (smode == SLIB_MODE_COMPRESS)
{
if (SlibFindEnumEntry(_listCompressTypes, *stype)==NULL)
return(SlibErrorUnsupportedFormat);
}
else if (smode == SLIB_MODE_DECOMPRESS)
{
/* for decompression we need the first buffer to open the codecs */
if (!buffer || bufsize==0)
return(SlibErrorBadArgument);
}
if ((Info = (SlibInfo_t *)ScAlloc(sizeof(SlibInfo_t))) == NULL)
return(SlibErrorMemory);
slibInitInfo(Info);
Info->Mode=smode;
slibAddPin(Info, SLIB_DATA_COMPRESSED, "Compressed");
if (smode == SLIB_MODE_DECOMPRESS)
{
status=SlibAddBuffer((SlibHandle_t *)Info, SLIB_DATA_COMPRESSED, buffer, bufsize);
if (status!=SlibErrorNone)
return(status);
}
*handle=(SlibHandle_t)Info;
if ((status=slibOpen(handle, smode, stype))!=SlibErrorNone)
*handle = NULL;
return(status);
}
SlibStatus_t SlibOpenFile(SlibHandle_t *handle, SlibMode_t smode,
SlibType_t *stype, char *filename)
{
SlibInfo_t *Info=NULL;
SlibStatus_t status;
_SlibDebug(_VERBOSE_,printf("SlibOpenFile()\n") );
if (!handle)
return(SlibErrorBadHandle);
*handle = NULL;
if (!stype)
return(SlibErrorBadArgument);
if (!filename)
return(SlibErrorBadArgument);
if (smode == SLIB_MODE_COMPRESS)
{
if (SlibFindEnumEntry(_listCompressTypes, *stype)==NULL)
return(SlibErrorUnsupportedFormat);
if ((Info = (SlibInfo_t *) ScAlloc(sizeof(SlibInfo_t))) == NULL)
return(SlibErrorMemory);
slibInitInfo(Info);
Info->Fd = ScFileOpenForWriting(filename, TRUE);
if (Info->Fd<0)
{
ScFree(Info);
return(SlibErrorWriting);
}
*handle=(SlibHandle_t)Info;
if ((status=slibOpen(handle, smode, stype))!=SlibErrorNone)
*handle = NULL;
return(status);
}
else if (smode == SLIB_MODE_DECOMPRESS)
{
if ((Info = (SlibInfo_t *)ScAlloc(sizeof(SlibInfo_t))) == NULL)
return(SlibErrorMemory);
slibInitInfo(Info);
Info->Fd = ScFileOpenForReading(filename);
if (Info->Fd<0)
{
ScFree(Info);
return(SlibErrorReading);
}
ScFileSize(filename, &Info->FileSize);
*handle=(SlibHandle_t)Info;
if ((status=slibOpen(handle, smode, stype))!=SlibErrorNone)
*handle = NULL;
return(status);
}
else
return(SlibErrorBadMode);
}
static SlibStatus_t slibOpen(SlibHandle_t *handle, SlibMode_t smode,
SlibType_t *stype)
{
SlibInfo_t *Info=(SlibInfo_t *)*handle;
unsigned char *buf;
unsigned dword size;
_SlibDebug(_VERBOSE_,printf("SlibOpenFile()\n") );
if (!Info)
return(SlibErrorMemory);
if (!stype)
return(SlibErrorBadArgument);
if (Info->SlibCB)
{
SlibMessage_t result;
_SlibDebug(_VERBOSE_,
printf("slibOpen() SlibCB(SLIB_MSG_OPEN)\n") );
result=(*(Info->SlibCB))((SlibHandle_t)Info,
SLIB_MSG_OPEN, (SlibCBParam1_t)0,
(SlibCBParam2_t)0, (void *)Info->SlibCBUserData);
}
if (smode == SLIB_MODE_COMPRESS)
{
Info->Mode = smode;
Info->Type = *stype;
SlibUpdateAudioInfo(Info);
SlibUpdateVideoInfo(Info);
switch (Info->Type)
{
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
case SLIB_TYPE_MPEG1_VIDEO:
Info->VideoStreams = 1;
if (SvOpenCodec (Info->Type==SLIB_TYPE_MPEG_SYSTEMS_MPEG2 ?
SV_MPEG2_ENCODE : SV_MPEG_ENCODE,
&Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
if (Info->Type==SLIB_TYPE_MPEG1_VIDEO)
break;
case SLIB_TYPE_MPEG1_AUDIO:
Info->AudioStreams = 1;
if (SaOpenCodec (SA_MPEG_ENCODE, &Info->Sah)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->AudioCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_AUDIO, "Audio");
break;
case SLIB_TYPE_MPEG2_VIDEO:
Info->VideoStreams = 1;
if (SvOpenCodec (SV_MPEG2_ENCODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
break;
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
case SLIB_TYPE_H261:
Info->VideoStreams = 1;
if (SvOpenCodec (SV_H261_ENCODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
break;
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
case SLIB_TYPE_H263:
Info->VideoStreams = 1;
if (SvOpenCodec (SV_H263_ENCODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
break;
#endif /* H263_SUPPORT */
#ifdef HUFF_SUPPORT
case SLIB_TYPE_SHUFF:
Info->VideoStreams = 1;
if (SvOpenCodec (SV_HUFF_ENCODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
break;
#endif /* HUFF_SUPPORT */
#ifdef G723_SUPPORT
case SLIB_TYPE_G723:
Info->AudioStreams = 1;
if (SaOpenCodec (SA_G723_ENCODE, &Info->Sah)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->AudioCodecState=SLIB_CODEC_STATE_OPEN;
slibAddPin(Info, SLIB_DATA_AUDIO, "Audio");
break;
#endif /*G723_SUPPORT*/
default:
return(SlibErrorUnsupportedFormat);
}
slibAddPin(Info, SLIB_DATA_COMPRESSED, "Compressed");
}
else if (smode == SLIB_MODE_DECOMPRESS)
{
Info->Mode = smode;
/*
** Determine the input data type
*/
if (slibLoadPin(Info, SLIB_DATA_COMPRESSED)==NULL)
return(SlibErrorReading);
if ((buf=SlibPeekBuffer(Info, SLIB_DATA_COMPRESSED, &size, NULL))==NULL
|| size<=0)
{
/* couldn't get any compressed data */
SlibClose((SlibHandle_t)Info);
return(SlibErrorReading);
}
Info->Type = slibGetDataFormat(buf, size, NULL, NULL);
/* if we can't determine the type, use stype as the type */
if (Info->Type==SLIB_TYPE_UNKNOWN && stype)
Info->Type=*stype;
if (SlibFindEnumEntry(_listDecompressTypes, Info->Type)==NULL)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
slibAddPin(Info, SLIB_DATA_AUDIO, "Audio");
slibAddPin(Info, SLIB_DATA_VIDEO, "Video");
if (SlibTypeIsMPEGMux(Info->Type))
{
/* need to select main streams for multiplexed streams */
Info->AudioMainStream=MPEG_AUDIO_STREAM_START;
Info->VideoMainStream=MPEG_VIDEO_STREAM_START;
/* private data may be needed - i.e. AC3 */
slibAddPin(Info, SLIB_DATA_PRIVATE, "Private");
}
SlibUpdateAudioInfo(Info);
SlibUpdateVideoInfo(Info);
if (Info->AudioStreams<=0)
slibRemovePin(Info, SLIB_DATA_AUDIO);
if (Info->VideoStreams<=0)
slibRemovePin(Info, SLIB_DATA_VIDEO);
slibRemovePin(Info, SLIB_DATA_PRIVATE); /* only used in init */
if (Info->AudioBitRate && Info->VideoBitRate)
{
if (!Info->VideoLengthKnown)
{
qword ms=((qword)Info->FileSize*80L)/
(Info->AudioBitRate+Info->VideoBitRate);
ms = (ms*75)/80; /* adjust for systems data */
Info->AudioLength = Info->VideoLength = (SlibTime_t)ms*100;
_SlibDebug(_SEEK_||_VERBOSE_,
ScDebugPrintf(Info->dbg,"slibOpen() FileSize=%ld VideoLength=%ld\n",
Info->FileSize, Info->VideoLength) );
}
else if (Info->VideoLengthKnown && Info->FramesPerSec)
Info->AudioLength = Info->VideoLength;
}
if (Info->TotalBitRate==0)
Info->TotalBitRate=Info->AudioBitRate +
((Info->VideoBitRate>100000000)?0:Info->VideoBitRate);
_SlibDebug(_SEEK_||_VERBOSE_,
ScDebugPrintf(Info->dbg,"AudioLength=%ld VideoLength=%ld %s\n",
Info->AudioLength, Info->VideoLength,
Info->VideoLengthKnown?"(known)":"") );
if (Info->AudioType==SLIB_TYPE_UNKNOWN &&
Info->VideoType==SLIB_TYPE_UNKNOWN)
return(SlibErrorUnsupportedFormat);
switch (Info->AudioType)
{
case SLIB_TYPE_UNKNOWN:
break;
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_AUDIO:
if (SaOpenCodec (SA_MPEG_DECODE, &Info->Sah)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->AudioCodecState=SLIB_CODEC_STATE_OPEN;
break;
#endif /* MPEG_SUPPORT */
#ifdef GSM_SUPPORT
if (SaOpenCodec (SA_GSM_DECODE, &Info->Sah)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->AudioCodecState=SLIB_CODEC_STATE_OPEN;
break;
#endif /* GSM_SUPPORT */
#ifdef AC3_SUPPORT
case SLIB_TYPE_AC3_AUDIO:
if (SaOpenCodec (SA_AC3_DECODE, &Info->Sah)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->AudioCodecState=SLIB_CODEC_STATE_OPEN;
break;
#endif /* AC3_SUPPORT */
#ifdef G723_SUPPORT
case SLIB_TYPE_G723:
if (SaOpenCodec (SA_G723_DECODE, &Info->Sah)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->AudioCodecState=SLIB_CODEC_STATE_OPEN;
break;
#endif /* G723_SUPPORT */
} /* AudioType */
switch (Info->VideoType)
{
case SLIB_TYPE_UNKNOWN:
break;
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_VIDEO:
if (SvOpenCodec (SV_MPEG_DECODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
_SlibDebug(_DEBUG_,printf("VideoCodecState=OPEN\n"));
break;
case SLIB_TYPE_MPEG2_VIDEO:
if (SvOpenCodec (SV_MPEG2_DECODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
_SlibDebug(_DEBUG_,printf("VideoCodecState=OPEN\n"));
break;
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
case SLIB_TYPE_H261:
if (SvOpenCodec (SV_H261_DECODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
_SlibDebug(_DEBUG_,printf("VideoCodecState=OPEN\n"));
break;
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
case SLIB_TYPE_H263:
if (SvOpenCodec (SV_H263_DECODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
_SlibDebug(_DEBUG_,printf("VideoCodecState=OPEN\n"));
break;
#endif /* H263_SUPPORT */
#ifdef HUFF_SUPPORT
case SLIB_TYPE_SHUFF:
if (SvOpenCodec (SV_HUFF_DECODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
_SlibDebug(_DEBUG_,printf("VideoCodecState=OPEN\n"));
break;
#endif /* HUFF_SUPPORT */
#ifdef JPEG_SUPPORT
case SLIB_TYPE_JPEG:
case SLIB_TYPE_MJPG:
if (SvOpenCodec (SV_JPEG_DECODE, &Info->Svh)!=SvErrorNone)
{
SlibClose((SlibHandle_t)Info);
return(SlibErrorUnsupportedFormat);
}
Info->VideoCodecState=SLIB_CODEC_STATE_OPEN;
_SlibDebug(_DEBUG_,printf("VideoCodecState=OPEN\n"));
break;
#endif /* JPEG_SUPPORT */
} /* VideoType */
}
else
return(SlibErrorBadMode);
*stype = Info->Type;
return(SlibErrorNone);
}
SlibStatus_t SlibAddBuffer(SlibHandle_t handle, SlibDataType_t dtype,
void *buffer, unsigned dword bufsize)
{
SvStatus_t status;
SlibInfo_t *Info=(SlibInfo_t *)handle;
SlibPin_t *dstpin;
if (!handle)
return(SlibErrorBadHandle);
dstpin = slibGetPin(Info, dtype);
if (dstpin==NULL || buffer==NULL)
return(SlibErrorBadArgument);
if (Info->SlibCB)
{
status=slibManageUserBuffer(Info, buffer, bufsize, NULL);
if (status!=SlibErrorNone)
return(status);
status=slibAddBufferToPin(dstpin, buffer, bufsize, SLIB_TIME_NONE);
}
else if (!SlibValidBuffer(buffer))
{
/* we need to create a SLIB allocated buffer to copy the
* output to and then add to the compressed data pin
*/
unsigned char *bufptr=SlibAllocBuffer(bufsize);
if (!bufptr)
return(SlibErrorMemory);
memcpy(bufptr, buffer, bufsize);
status=slibAddBufferToPin(dstpin, bufptr, bufsize, SLIB_TIME_NONE);
}
else
status=slibAddBufferToPin(dstpin, buffer, bufsize, SLIB_TIME_NONE);
if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
ScBitstream_t *BS;
Info->IOError=FALSE;
/* reset end-of-input flags in bitstream objects */
if (Info->Svh)
{
BS=SvGetDataSource(Info->Svh);
if (BS && BS->EOI) ScBSReset(BS);
}
if (Info->Sah)
{
BS=SaGetDataSource(Info->Sah);
if (BS && BS->EOI) ScBSReset(BS);
}
}
return(status);
}
SlibStatus_t SlibAddBufferEx(SlibHandle_t handle, SlibDataType_t dtype,
void *buffer, unsigned dword bufsize,
void *userdata)
{
SvStatus_t status;
SlibInfo_t *Info=(SlibInfo_t *)handle;
SlibPin_t *dstpin;
if (!handle)
return(SlibErrorBadHandle);
dstpin = slibGetPin(Info, dtype);
if (dstpin==NULL || buffer==NULL)
return(SlibErrorBadArgument);
status=slibManageUserBuffer(Info, buffer, bufsize, userdata);
if (status!=SlibErrorNone)
return(status);
status=slibAddBufferToPin(dstpin, buffer, bufsize, SLIB_TIME_NONE);
return(status);
}
SlibStatus_t slibStartVideo(SlibInfo_t *Info, SlibBoolean_t fillbuf)
{
SvStatus_t status=SvErrorNone;
_SlibDebug(_VERBOSE_,printf("slibStartVideo()\n") );
if (Info->VideoCodecState==SLIB_CODEC_STATE_NONE ||
Info->VideoCodecState==SLIB_CODEC_STATE_BEGUN)
{
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"slibStartVideo(filebuf=%d) %s\n",
fillbuf,Info->VideoCodecState==SLIB_CODEC_STATE_NONE ? "NONE" : "BEGUN") );
return(SlibErrorNone);
}
if (Info->VideoCodecState==SLIB_CODEC_STATE_OPEN)
{
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"slibStartVideo(filebuf=%d) OPEN\n",
fillbuf));
if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
if (Info->Type==SLIB_TYPE_YUV_AVI)
{
Info->VideoCodecState=SLIB_CODEC_STATE_BEGUN;
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"VideoCodecState=BEGUN\n"));
}
else if (Info->Svh)
{
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"SvRegisterCallback()\n") );
status = SvRegisterCallback(Info->Svh, VDecompressCallback, (void *)Info);
/* if codec is not bitstreaming, don't use callbacks */
if (status==SlibErrorNone && SvGetDataSource(Info->Svh)==NULL)
{
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"SvRegisterCallback(NULL)\n") );
status = SvRegisterCallback(Info->Svh, NULL, NULL);
}
_SlibDebug(_WARN_ && status!=SvErrorNone,
ScDebugPrintf(Info->dbg,"SvRegisterCallback() %s\n",
ScGetErrorStr(status)) );
Info->VideoCodecState=SLIB_CODEC_STATE_INITED;
_SlibDebug(_DEBUG_,printf("VideoCodecState=INITED\n"));
}
}
else if (Info->Mode==SLIB_MODE_COMPRESS)
{
if (Info->TotalBitRate==0)
{
#ifdef MPEG_SUPPORT
if (Info->Type==SLIB_TYPE_MPEG_SYSTEMS || /* default to 1XCDROM rate */
Info->Type==SLIB_TYPE_MPEG_SYSTEMS_MPEG2)
SlibSetParamInt((SlibHandle_t)Info, SLIB_STREAM_ALL,
SLIB_PARAM_BITRATE, 44100*16*2);
#endif
slibValidateBitrates(Info); /* update bitrates */
}
if (Info->Svh)
{
status = SvRegisterCallback(Info->Svh, VCompressCallback, (void *)Info);
_SlibDebug(_WARN_ && status!=SvErrorNone,
ScDebugPrintf(Info->dbg,"SvRegisterCallback() %s\n",
ScGetErrorStr(status)) );
/* if codec is not bitstreaming, don't use callbacks */
if (status==SlibErrorNone && SvGetDataDestination(Info->Svh)==NULL)
status = SvRegisterCallback(Info->Svh, NULL, NULL);
Info->VideoCodecState=SLIB_CODEC_STATE_INITED;
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"VideoCodecState=BEGUN\n"));
}
}
}
if (Info->VideoCodecState==SLIB_CODEC_STATE_INITED ||
Info->VideoCodecState==SLIB_CODEC_STATE_REPOSITIONING)
{
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,
"slibStartVideo(fillbuf=%d) INITED || REPOSITIONING\n",fillbuf));
if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
if (Info->Type==SLIB_TYPE_YUV_AVI)
{
if (Info->CompVideoFormat->biCompression !=
Info->VideoFormat->biCompression &&
Info->Multibuf==NULL)
{
Info->MultibufSize=Info->ImageSize;
Info->Multibuf = SlibAllocSharedBuffer(Info->MultibufSize, NULL);
}
}
else if (Info->Svh)
{
int mbufsize;
if (1) /* fillbuf && Info->CodecVideoFormat) */
{
Info->CodecVideoFormat->biCompression=
SlibGetParamInt((SlibHandle_t)Info, SLIB_STREAM_MAINVIDEO,
SLIB_PARAM_NATIVEVIDEOFORMAT);
if (Info->CodecVideoFormat->biCompression==0)
Info->CodecVideoFormat->biCompression=
Info->VideoFormat->biCompression;
}
else
{
Info->CodecVideoFormat->biCompression=
Info->VideoFormat->biCompression;
Info->CodecVideoFormat->biBitCount=
Info->VideoFormat->biBitCount;
}
slibValidateVideoParams(Info);
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,
"SvDecompressBegin(%c%c%c%c/%d bits,%c%c%c%c/%d bits)\n",
(Info->CompVideoFormat->biCompression)&0xFF,
(Info->CompVideoFormat->biCompression>>8)&0xFF,
(Info->CompVideoFormat->biCompression>>16)&0xFF,
(Info->CompVideoFormat->biCompression>>24)&0xFF,
Info->CompVideoFormat->biBitCount,
(Info->CodecVideoFormat->biCompression)&0xFF,
(Info->CodecVideoFormat->biCompression>>8)&0xFF,
(Info->CodecVideoFormat->biCompression>>16)&0xFF,
(Info->CodecVideoFormat->biCompression>>24)&0xFF,
Info->CodecVideoFormat->biBitCount) );
status=SvDecompressBegin(Info->Svh, Info->CompVideoFormat,
Info->CodecVideoFormat);
if (status==SvErrorNone)
{
Info->KeySpacing=(int)SvGetParamInt(Info->Svh, SV_PARAM_KEYSPACING);
Info->SubKeySpacing=(int)SvGetParamInt(Info->Svh,
SV_PARAM_SUBKEYSPACING);
Info->VideoCodecState=SLIB_CODEC_STATE_BEGUN;
Info->HeaderProcessed=TRUE; /* we must have processed header info */
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"VideoCodecState=BEGUN\n"));
}
else if (status==SvErrorEndBitstream)
return(SlibErrorNoBeginning);
else
{
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,"SvDecompressBegin() %s\n",
ScGetErrorStr(status)) );
return(SlibErrorUnsupportedFormat);
}
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"SvGetDecompressSize\n") );
SvGetDecompressSize(Info->Svh, &mbufsize);
if (Info->Multibuf==NULL || Info->MultibufSize<mbufsize)
{
if (Info->Multibuf) SlibFreeBuffer(Info->Multibuf);
Info->MultibufSize=mbufsize;
Info->Multibuf = SlibAllocSharedBuffer(Info->MultibufSize, NULL);
}
}
}
else if (Info->Mode==SLIB_MODE_COMPRESS && Info->Svh)
{
status=SvCompressBegin(Info->Svh, Info->CodecVideoFormat,
Info->CompVideoFormat);
if (status==SvErrorNone)
{
Info->KeySpacing=(int)SvGetParamInt(Info->Svh, SV_PARAM_KEYSPACING);
Info->SubKeySpacing=(int)SvGetParamInt(Info->Svh,
SV_PARAM_SUBKEYSPACING);
Info->VideoCodecState=SLIB_CODEC_STATE_BEGUN;
_SlibDebug(_DEBUG_,ScDebugPrintf(Info->dbg,"VideoCodecState=BEGUN\n"));
}
else
{
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,"SvCompressBegin() %s\n",
ScGetErrorStr(status)) );
return(SlibErrorUnsupportedFormat);
}
}
}
if (Info->VideoCodecState==SLIB_CODEC_STATE_BEGUN)
return(SlibErrorNone);
else
return(SlibErrorInit);
}
static SlibStatus_t slibStartAudio(SlibInfo_t *Info)
{
SvStatus_t status=SvErrorNone;
_SlibDebug(_VERBOSE_,printf("slibStartAudio()\n") );
if (Info->AudioCodecState==SLIB_CODEC_STATE_NONE ||
Info->AudioCodecState==SLIB_CODEC_STATE_BEGUN)
{
_SlibDebug(_DEBUG_,printf("slibStartAudio() %s\n",
Info->AudioCodecState==SLIB_CODEC_STATE_NONE ? "NONE" : "BEGUN") );
return(SlibErrorNone);
}
if (Info->AudioCodecState==SLIB_CODEC_STATE_OPEN)
{
_SlibDebug(_DEBUG_,printf("slibStartAudio() OPEN\n"));
if (Info->Sah)
{
if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
status = SaRegisterCallback(Info->Sah, ADecompressCallback, (void *)Info);
if (status!=SaErrorNone)
{
_SlibDebug(_WARN_, printf("SaRegisterCallback() ",
ScGetErrorStr(status)) );
return(SlibErrorInternal);
}
status = SaSetDataSource(Info->Sah, SA_USE_BUFFER_QUEUE, 0, (void *)Info, 0);
_SlibDebug(_WARN_ && status!=SaErrorNone,
printf("SaSetDataSource() ", ScGetErrorStr(status)) );
Info->AudioCodecState=SLIB_CODEC_STATE_INITED;
_SlibDebug(_DEBUG_,printf("AudioCodecState=INITED\n"));
}
else if (Info->Mode==SLIB_MODE_COMPRESS)
{
if (Info->TotalBitRate==0)
{
#ifdef MPEG_SUPPORT
/* default to 1X CDROM rate */
if (Info->Type==SLIB_TYPE_MPEG_SYSTEMS ||
Info->Type==SLIB_TYPE_MPEG_SYSTEMS_MPEG2)
SlibSetParamInt((SlibHandle_t)Info, SLIB_STREAM_ALL,
SLIB_PARAM_BITRATE, 44100*16*2);
#endif
slibValidateBitrates(Info); /* update bitrates */
}
status = SaRegisterCallback(Info->Sah, ACompressCallback, (void *)Info);
_SlibDebug(_WARN_ && status!=SaErrorNone,
printf("SaRegisterCallback() %s\n", ScGetErrorStr(status)) );
status = SaSetDataDestination(Info->Sah, SA_USE_BUFFER_QUEUE, 0,
(void *)Info, 0);
_SlibDebug(_WARN_ && status!=SaErrorNone,
printf("SaSetDataDestination() %s\n",
ScGetErrorStr(status)) );
Info->AudioCodecState=SLIB_CODEC_STATE_INITED;
_SlibDebug(_DEBUG_,printf("AudioCodecState=INITED\n"));
}
}
}
if (Info->AudioCodecState==SLIB_CODEC_STATE_INITED ||
Info->AudioCodecState==SLIB_CODEC_STATE_REPOSITIONING)
{
_SlibDebug(_DEBUG_,printf("slibStartAudio() INITED || REPOSITIONING\n"));
if (Info->Sah)
{
if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
Info->AudiobufUsed=0;
/* don't want codec to search through to much data for start */
status=SaDecompressBegin(Info->Sah, Info->CompAudioFormat,
Info->AudioFormat);
if (status==SaErrorNone)
{
Info->AudioCodecState=SLIB_CODEC_STATE_BEGUN;
_SlibDebug(_DEBUG_,printf("AudioCodecState=BEGUN\n"));
}
else if (status==SlibErrorNoBeginning)
return(SlibErrorEndOfStream);
else
{
_SlibDebug(_WARN_, printf("SaDecompressBegin() %s\n",
ScGetErrorStr(status)) );
return(SlibErrorUnsupportedFormat);
}
}
else if (Info->Mode==SLIB_MODE_COMPRESS)
{
status=SaCompressBegin(Info->Sah, Info->AudioFormat,
Info->CompAudioFormat);
if (status==SvErrorNone)
{
Info->AudioCodecState=SLIB_CODEC_STATE_BEGUN;
_SlibDebug(_DEBUG_,printf("AudioCodecState=BEGUN\n"));
}
else
{
_SlibDebug(_WARN_, printf("SaCompressBegin() %s\n",
ScGetErrorStr(status)) );
return(SlibErrorUnsupportedFormat);
}
}
}
}
return(SlibErrorNone);
}
SlibStatus_t SlibRegisterVideoBuffer(SlibHandle_t handle,
void *buffer, unsigned dword bufsize)
{
SvStatus_t status;
SlibInfo_t *Info=(SlibInfo_t *)handle;
dword mbufsize;
if (!handle)
return(SlibErrorBadHandle);
if (Info->Multibuf) SlibFreeBuffer(Info->Multibuf);
Info->MultibufSize=bufsize;
Info->Multibuf = buffer;
status=slibManageUserBuffer(Info, buffer, bufsize, NULL);
if (Info->Svh)
{
SvGetDecompressSize(Info->Svh, &mbufsize);
if (bufsize<(unsigned dword)mbufsize)
return(SlibErrorBufSize);
}
return(status);
}
SlibStatus_t SlibReadData(SlibHandle_t handle, SlibStream_t stream,
void **databuf, unsigned dword *databufsize,
SlibStream_t *readstream)
{
SlibInfo_t *Info=(SlibInfo_t *)handle;
int pinid;
SlibPin_t *pin;
SlibTime_t ptimestamp;
_SlibDebug(_VERBOSE_, printf("SlibReadDATA()\n") );
if (!handle)
return(SlibErrorBadHandle);
if (!databuf) /* we're querying to find out how much data is queued */
{
if (!databufsize)
return(SlibErrorBadArgument);
if (Info->Mode==SLIB_MODE_COMPRESS)
pinid=SLIB_DATA_COMPRESSED;
else if (stream==SLIB_STREAM_MAINVIDEO)
pinid=SLIB_DATA_VIDEO;
else if (stream==SLIB_STREAM_MAINAUDIO)
pinid=SLIB_DATA_AUDIO;
else
{
*databufsize=(unsigned dword)slibDataOnPins(Info); /* get amount of data on all pins */
return(SlibErrorNone);
}
*databufsize=(unsigned dword)slibDataOnPin(Info, SLIB_DATA_COMPRESSED);
return(SlibErrorNone);
}
if (Info->Mode==SLIB_MODE_COMPRESS)
{
pinid=SLIB_DATA_COMPRESSED;
stream=SLIB_STREAM_ALL;
/* flush out all compressed data */
if (Info->Sah)
ScBSFlush(SaGetDataDestination(Info->Sah));
if (Info->Svh)
ScBSFlush(SvGetDataDestination(Info->Svh));
}
else /* SLIB_MODE_DECOMPRESS */
{
if (stream==SLIB_STREAM_ALL && (Info->AudioStreams || Info->VideoStreams))
{
if (Info->AudioStreams==0) /* there's only video */
stream=SLIB_STREAM_MAINVIDEO;
else if (Info->VideoStreams==0) /* there's only audio */
stream=SLIB_STREAM_MAINAUDIO;
else if (slibDataOnPin(Info, SLIB_DATA_AUDIO)>
slibDataOnPin(Info, SLIB_DATA_VIDEO)) /* more audio than video */
stream=SLIB_STREAM_MAINAUDIO;
else
stream=SLIB_STREAM_MAINVIDEO;
}
switch (stream) /* translate stream to pin */
{
case SLIB_STREAM_MAINVIDEO:
pinid=SLIB_DATA_VIDEO;
break;
case SLIB_STREAM_MAINAUDIO:
pinid=SLIB_DATA_AUDIO;
break;
default:
return(SlibErrorBadStream);
}
}
if (readstream)
*readstream=stream;
pin=slibLoadPin(Info, pinid);
if (pin==NULL)
return(Info->Mode==SLIB_MODE_COMPRESS?SlibErrorNoData:SlibErrorBadStream);
if (stream==SLIB_STREAM_MAINVIDEO && Info->Mode==SLIB_MODE_DECOMPRESS &&
Info->VideoPTimeCode==SLIB_TIME_NONE &&
SlibTypeIsMPEG(Info->Type))
{
/* search from GOP start */
dword i, iend;
SlibTime_t nexttime;
unsigned char *tmpbuf, *prevbuf=NULL;
unsigned dword tmpsize, bytessearched=0;
tmpbuf=SlibGetBuffer(Info, pinid, &tmpsize, &ptimestamp);
if (tmpbuf==NULL)
return(SlibErrorEndOfStream);
do {
for (i=0, iend=tmpsize-3; i<iend; i++)
if (tmpbuf[i]==0&&tmpbuf[i+1]==0&&tmpbuf[i+2]==1&&
(tmpbuf[i+3]==0xB8||tmpbuf[i+3]==0xB3))
break;
if (i<iend)
{
slibInsertBufferOnPin(pin, tmpbuf+i, tmpsize-i, ptimestamp);
tmpbuf=NULL;
break;
}
else if (tmpbuf[i]==0 && tmpbuf[i+1]==0 && tmpbuf[i+2]==1)
{
prevbuf=tmpbuf+tmpsize-3;
tmpbuf=SlibGetBuffer(Info, pinid, &tmpsize, &nexttime);
if (tmpbuf==NULL)
return(SlibErrorEndOfStream);
if (nexttime!=SLIB_TIME_NONE)
ptimestamp=nexttime;
if (tmpbuf[0]==0xB8||tmpbuf[0]==0xB3)
{
slibInsertBufferOnPin(pin, tmpbuf, tmpsize, nexttime);
slibInsertBufferOnPin(pin, prevbuf, 3, ptimestamp);
tmpbuf=NULL;
break;
}
else
SlibFreeBuffer(prevbuf);
}
else if (tmpbuf[i+1]==0 && tmpbuf[i+2]==0)
{
prevbuf=tmpbuf+tmpsize-2;
tmpbuf=SlibGetBuffer(Info, pinid, &tmpsize, &nexttime);
if (tmpbuf==NULL)
return(SlibErrorEndOfStream);
if (nexttime!=SLIB_TIME_NONE)
ptimestamp=nexttime;
if (tmpbuf[0]==1 && (tmpbuf[1]==0xB8||tmpbuf[0]==0xB3))
{
slibInsertBufferOnPin(pin, tmpbuf, tmpsize, nexttime);
slibInsertBufferOnPin(pin, prevbuf, 2, ptimestamp);
tmpbuf=NULL;
break;
}
else
SlibFreeBuffer(prevbuf);
}
else if (tmpbuf[i+2]==0)
{
prevbuf=tmpbuf+tmpsize-1;
tmpbuf=SlibGetBuffer(Info, pinid, &tmpsize, &nexttime);
if (tmpbuf==NULL)
return(SlibErrorEndOfStream);
if (nexttime!=SLIB_TIME_NONE)
ptimestamp=nexttime;
if (tmpbuf[0]==0 && tmpbuf[1]==1 && (tmpbuf[2]==0xB8||tmpbuf[0]==0xB3))
{
slibInsertBufferOnPin(pin, tmpbuf, tmpsize, nexttime);
slibInsertBufferOnPin(pin, prevbuf, 1, ptimestamp);
tmpbuf=NULL;
break;
}
else
SlibFreeBuffer(prevbuf);
}
else
{
SlibFreeBuffer(tmpbuf);
tmpbuf=SlibGetBuffer(Info, pinid, &tmpsize, &nexttime);
if (tmpbuf==NULL)
return(SlibErrorEndOfStream);
if (nexttime!=SLIB_TIME_NONE)
ptimestamp=nexttime;
}
bytessearched+=tmpsize;
} while (tmpbuf && bytessearched<512*1024);
}
if (*databuf==NULL)
*databuf=SlibGetBuffer(Info, pinid, databufsize, &ptimestamp);
else
*databufsize=slibFillBufferFromPin(Info, pin, *databuf, *databufsize,
&ptimestamp);
if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
if (ptimestamp!=SLIB_TIME_NONE)
switch (stream) /* set presentation timecodes */
{
case SLIB_STREAM_MAINVIDEO:
Info->VideoPTimeCode=ptimestamp;
_SlibDebug(_TIMECODE_ || _VERBOSE_,
printf("SlibReadData() VideoPTimeCode=%ld\n", ptimestamp) );
break;
case SLIB_STREAM_MAINAUDIO:
Info->AudioPTimeCode=ptimestamp;
_SlibDebug(_TIMECODE_ || _VERBOSE_,
printf("SlibReadData() AudioPTimeCode=%ld\n", ptimestamp) );
break;
}
else if (stream==SLIB_STREAM_MAINVIDEO &&
Info->VideoPTimeCode==SLIB_TIME_NONE)
Info->VideoPTimeCode=SLIB_TIME_UNKNOWN;
}
if (*databuf==NULL || *databufsize==0)
{
if (!slibDataOnPin(Info, pinid))
return(SlibErrorEndOfStream);
else
return(SlibErrorReading);
}
return(SlibErrorNone);
}
SlibStatus_t SlibReadVideo(SlibHandle_t handle, SlibStream_t stream,
void **videobuf, unsigned dword *videobufsize)
{
SlibInfo_t *Info=(SlibInfo_t *)handle;
SvStatus_t status=SvErrorNone;
unsigned char *imagebuf=NULL;
SlibTime_t startvideotime;
_SlibDebug(_VERBOSE_, printf("SlibReadVideo()\n") );
if (!handle)
return(SlibErrorBadHandle);
if (!videobuf)
return(SlibErrorBadArgument);
/*
imagesize=(Info->Width*Info->Height*3)/2;
if (videobufsize<imagesize)
return(SlibErrorBufSize);
*/
if (Info->Mode!=SLIB_MODE_DECOMPRESS)
return(SlibErrorBadMode);
if (Info->VideoFormat==NULL || Info->CodecVideoFormat==NULL ||
Info->CompVideoFormat==NULL)
return(SlibErrorUnsupportedFormat);
if ((status=slibStartVideo(Info, (SlibBoolean_t)((*videobuf==NULL)?FALSE:TRUE)))
!=SlibErrorNone)
return(status);
startvideotime=Info->VideoTimeStamp;
switch(Info->VideoType)
{
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_VIDEO:
case SLIB_TYPE_MPEG2_VIDEO:
do {
_SlibDebug(_DEBUG_, printf("SvDecompressMPEG()\n") );
status = SvDecompressMPEG(Info->Svh, Info->Multibuf,
Info->MultibufSize, &imagebuf);
_SlibDebug(_WARN_ && status!=SvErrorNone,
printf("SvDecompressMPEG() %s\n",
ScGetErrorStr(status)) );
} while(status == SvErrorNotDecompressable);
if (status==SvErrorNone)
SlibAllocSubBuffer(imagebuf, Info->CodecVideoFormat->biSizeImage);
_SlibDebug(_SEEK_>1, printf("timecode=%d ms framenum=%d\n",
SvGetParamInt(Info->Svh, SV_PARAM_CALCTIMECODE),
SvGetParamInt(Info->Svh, SV_PARAM_FRAME) ) );
break;
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
case SLIB_TYPE_H261:
do {
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"SvDecompressH261()\n") );
status = SvDecompressH261(Info->Svh, Info->Multibuf,
Info->MultibufSize,
&imagebuf);
} while(status == SvErrorNotDecompressable);
if (status==SvErrorNone)
SlibAllocSubBuffer(imagebuf, Info->CodecVideoFormat->biSizeImage);
break;
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
case SLIB_TYPE_H263:
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"SvDecompress(%d bytes)\n", Info->MultibufSize) );
status=SvDecompress(Info->Svh, NULL, 0,
Info->Multibuf, Info->MultibufSize);
imagebuf=Info->Multibuf;
if (status==SvErrorNone)
SlibAllocSubBuffer(imagebuf, Info->CodecVideoFormat->biSizeImage);
break;
#endif /* H263_SUPPORT */
#ifdef JPEG_SUPPORT
case SLIB_TYPE_JPEG:
case SLIB_TYPE_MJPG:
{
unsigned dword bufsize;
unsigned char *buf;
buf=SlibGetBuffer(Info, SLIB_DATA_VIDEO, &bufsize, NULL);
if (buf)
{
/* ScDumpChar(buf, 10000, 0); */
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"SvDecompress(%d bytes)\n", bufsize) );
status=SvDecompress(Info->Svh, buf, bufsize,
Info->Multibuf, Info->MultibufSize);
imagebuf=Info->Multibuf;
SlibFreeBuffer(buf);
}
else
status=SvErrorForeign;
if (status==SvErrorNone)
SlibAllocSubBuffer(imagebuf, Info->CodecVideoFormat->biSizeImage);
}
break;
#endif /* JPEG_SUPPORT */
#ifdef HUFF_SUPPORT
case SLIB_TYPE_SHUFF:
if (*videobuf==NULL)
{
if (Info->Imagebuf==NULL &&
(Info->Imagebuf=SlibAllocBuffer(Info->ImageSize))==NULL)
return(SlibErrorMemory);
imagebuf=Info->Imagebuf;
}
else
imagebuf=*videobuf;
do {
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"SvDecompress()\n") );
status=SvDecompress(Info->Svh, NULL, 0,
imagebuf, Info->CodecVideoFormat->biSizeImage);
} while(status == SvErrorNotDecompressable);
if (status==SvErrorNone)
SlibAllocSubBuffer(imagebuf, Info->CodecVideoFormat->biSizeImage);
break;
#endif /* HUFF_SUPPORT */
case SLIB_TYPE_RASTER:
case SLIB_TYPE_YUV:
if (*videobuf && videobufsize && *videobufsize==0)
return(SlibErrorBadArgument);
imagebuf=SlibGetBuffer(Info, SLIB_DATA_VIDEO, videobufsize, NULL);
if (*videobufsize==0)
status=SvErrorEndBitstream;
_SlibDebug(_DEBUG_,
ScDebugPrintf(Info->dbg,"Video frame size = %d ImageSize=%d\n",
*videobufsize, Info->ImageSize) );
break;
default:
return(SlibErrorUnsupportedFormat);
}
if (status==SvErrorNone)
{
/* format conversion */
if (Info->Sch==NULL) /* start the format converter */
{
if (Info->Svh) /* compressed video format */
{
unsigned dword fourcc=(unsigned dword)SvGetParamInt(Info->Svh, SV_PARAM_FINALFORMAT);
if (fourcc)
{
Info->CodecVideoFormat->biCompression=fourcc;
Info->CodecVideoFormat->biBitCount=
(WORD)slibCalcBits(fourcc, Info->CodecVideoFormat->biBitCount);
}
}
else /* uncompressed video format */
memcpy(Info->CodecVideoFormat, Info->CompVideoFormat, sizeof(BITMAPINFOHEADER));
if (SconOpen(&Info->Sch, SCON_MODE_VIDEO, (void *)Info->CodecVideoFormat, (void *)Info->VideoFormat)
!=SconErrorNone)
return(SlibErrorUnsupportedFormat);
if (Info->Stride)
SconSetParamInt(Info->Sch, SCON_OUTPUT, SCON_PARAM_STRIDE, Info->Stride);
}
if (SconIsSame(Info->Sch) && *videobuf == NULL) /* no conversion */
*videobuf=imagebuf;
else
{
if (*videobuf == NULL && (*videobuf=SlibAllocBuffer(Info->ImageSize))==NULL)
return(SlibErrorMemory);
if (SconConvert(Info->Sch, imagebuf, Info->CodecVideoFormat->biSizeImage,
*videobuf, Info->ImageSize) != SconErrorNone)
{
SlibFreeBuffer(imagebuf); /* free decompressed image */
return(SlibErrorUnsupportedFormat);
}
SlibFreeBuffer(imagebuf); /* free decompressed image */
}
*videobufsize = Info->ImageSize;
/* update stats */
if (Info->stats && Info->stats->Record)
Info->stats->FramesProcessed++;
if (startvideotime==Info->VideoTimeStamp) /* video time hasn't changed */
slibAdvancePositions(Info, 1);
}
else
{
if (status==ScErrorEndBitstream ||
!slibDataOnPin(Info, SLIB_DATA_VIDEO))
{
if (Info->FileSize>0 && !Info->VideoLengthKnown)
slibUpdateLengths(Info);
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,"SlibReadVideo() %s\n",
ScGetErrorStr(status)) );
return(SlibErrorEndOfStream);
}
_SlibDebug(_WARN_, printf("SlibReadVideo() %s\n",
ScGetErrorStr(status)) );
return(SlibErrorReading);
}
return(SlibErrorNone);
}
SlibStatus_t SlibReadAudio(SlibHandle_t handle, SlibStream_t stream,
void *audiobuf, unsigned dword *audiobufsize)
{
SlibInfo_t *Info=(SlibInfo_t *)handle;
SvStatus_t status=SaErrorNone;
unsigned dword totalbytes=0, bytes_since_timeupdate=0;
SlibTime_t startaudiotime;
#ifdef _SLIBDEBUG_
SlibTime_t calcaudiotime;
#endif
_SlibDebug(_VERBOSE_, printf("SlibReadAudio(audiobufsize=%d, time=%d)\n",
*audiobufsize, Info->AudioTimeStamp) );
if (!handle)
return(SlibErrorBadHandle);
if (Info->Mode!=SLIB_MODE_DECOMPRESS)
return(SlibErrorBadMode);
if (Info->AudioFormat==NULL)
return(SlibErrorUnsupportedFormat);
if ((status=slibStartAudio(Info))!=SlibErrorNone)
return(status);
#ifdef _SLIBDEBUG_
calcaudiotime=Info->AudioTimeStamp;
#endif
startaudiotime=Info->AudioTimeStamp;
switch(Info->AudioType)
{
case SLIB_TYPE_PCM:
totalbytes=slibFillBufferFromPin(Info,
slibGetPin(Info, SLIB_DATA_AUDIO),
(unsigned char *)audiobuf, *audiobufsize,
NULL);
if (totalbytes==0)
status=ScErrorEndBitstream;
*audiobufsize = totalbytes;
bytes_since_timeupdate = totalbytes;
break;
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_AUDIO:
{
unsigned dword bytes;
/* see if some bytes of audio are left in the temp audio buffer */
if (Info->Audiobuf && Info->AudiobufUsed>0)
{
_SlibDebug(_DEBUG_,
printf("SlibReadAudio() Audiobuf contains %d bytes\n",
Info->AudiobufUsed) );
if (*audiobufsize>=Info->AudiobufUsed)
{
memcpy(audiobuf, Info->Audiobuf, Info->AudiobufUsed);
totalbytes=Info->AudiobufUsed;
Info->AudiobufUsed=0;
}
else
{
memcpy(audiobuf, Info->Audiobuf, *audiobufsize);
totalbytes=*audiobufsize;
Info->AudiobufUsed-=*audiobufsize;
memcpy(Info->Audiobuf, Info->Audiobuf+*audiobufsize,
Info->AudiobufUsed);
}
}
/* need to alloc a temp audio buffer? */
if (!Info->Audiobuf || Info->AudiobufSize<
*audiobufsize+MPEG1_AUDIO_FRAME_SIZE*4)
{
unsigned char *newbuf;
/* enlarge Audiobuf or alloc it for the first time */
_SlibDebug(_DEBUG_,
printf("SlibReadAudio() enlarging Audiobuf: %d->%d bytes\n",
Info->AudiobufSize,*audiobufsize+MPEG1_AUDIO_FRAME_SIZE*4) );
newbuf=SlibAllocBuffer(*audiobufsize+MPEG1_AUDIO_FRAME_SIZE*4);
if (!newbuf)
return(SlibErrorMemory);
Info->AudiobufSize=*audiobufsize+MPEG1_AUDIO_FRAME_SIZE*4;
if (Info->Audiobuf)
SlibFreeBuffer(Info->Audiobuf);
Info->Audiobuf=newbuf;
Info->AudiobufUsed=0;
}
if (*audiobufsize>=MPEG1_AUDIO_FRAME_SIZE*4)
{
unsigned dword stopbytes=*audiobufsize-(MPEG1_AUDIO_FRAME_SIZE*4)+1;
while (status==SaErrorNone && totalbytes<stopbytes)
{
bytes = *audiobufsize - totalbytes;
_SlibDebug(_DEBUG_,
printf("SaDecompress(bytes=%d) in totalbytes=%d\n",
bytes, totalbytes) );
status = SaDecompress(Info->Sah, NULL, 0,
(unsigned char *)audiobuf+totalbytes, &bytes);
_SlibDebug(_DEBUG_, printf("SaDecompress() out: bytes=%d\n",
bytes) );
totalbytes += bytes;
if (Info->AudioTimeStamp!=startaudiotime)
{
startaudiotime=Info->AudioTimeStamp;
bytes_since_timeupdate=bytes;
}
else
bytes_since_timeupdate+=bytes;
}
}
if (totalbytes<*audiobufsize && status==SaErrorNone)
{
unsigned dword neededbytes=*audiobufsize-totalbytes;
while (status==SaErrorNone && Info->AudiobufUsed<neededbytes)
{
bytes = *audiobufsize - totalbytes;
_SlibDebug(_DEBUG_, printf("SaDecompress() in totalbytes=%d\n",
totalbytes) );
status = SaDecompress(Info->Sah, NULL, 0,
(unsigned char *)Info->Audiobuf+Info->AudiobufUsed, &bytes);
_SlibDebug(_DEBUG_, printf("SaDecompress() out, %d bytes\n",
bytes) );
Info->AudiobufUsed += bytes;
}
if (Info->AudiobufUsed>0)
{
if (Info->AudiobufUsed>neededbytes) /* complete buffer returned */
{
memcpy((unsigned char*)audiobuf+totalbytes,
Info->Audiobuf, neededbytes);
Info->AudiobufUsed-=neededbytes;
memcpy(Info->Audiobuf, Info->Audiobuf+neededbytes,
Info->AudiobufUsed);
totalbytes+=neededbytes;
bytes_since_timeupdate+=neededbytes;
}
else /* partially filled buffer */
{
memcpy((unsigned char*)audiobuf+totalbytes, Info->Audiobuf,
Info->AudiobufUsed);
totalbytes+=Info->AudiobufUsed;
Info->AudiobufUsed=0;
}
}
}
*audiobufsize = totalbytes;
_SlibDebug(_WARN_>1 && totalbytes>0 &&
totalbytes!=*audiobufsize,
printf("SlibReadAudio(audiobufsize=%d bytes) totalbytes=%d\n",
*audiobufsize, totalbytes) );
}
break;
#endif /* MPEG_SUPPORT */
#ifdef AC3_SUPPORT
case SLIB_TYPE_AC3_AUDIO:
{
unsigned dword bytes;
unsigned int framesize;
unsigned int buffersize;
int samplesize;
int buffers;
unsigned char *pointers[3];
int i;
if (Info->Channels>2)
{
framesize = AC3_FRAME_SIZE*((Info->BitsPerSample+7)/8)
*Info->Channels;
samplesize=Info->Channels*((Info->BitsPerSample+7)/8);
buffers = (Info->Channels+1)/2;
buffersize = (*audiobufsize/samplesize/buffers)*samplesize;
for(i=0; i<buffers; i++)
pointers[i]=(unsigned char *)audiobuf+buffersize*i;
if (*audiobufsize>=framesize)
{
while (status==SaErrorNone && totalbytes<buffersize)
{
bytes = buffersize - totalbytes;
_SlibDebug(_DEBUG_,printf("SaDecompressEx() in totalbytes=%d\n",
totalbytes) );
status = SaDecompressEx(Info->Sah, NULL, 0, pointers, &bytes);
_SlibDebug(_DEBUG_, printf("SaDecompress() out, %d bytes\n",
bytes) );
for(i=0;i<buffers;i++)
pointers[i]+=bytes;
totalbytes += bytes;
if (Info->AudioTimeStamp!=startaudiotime)
{
startaudiotime=Info->AudioTimeStamp;
bytes_since_timeupdate=bytes;
}
else
bytes_since_timeupdate+=bytes;
}
}
}
else
{
while (status==SaErrorNone && totalbytes<*audiobufsize)
{
bytes = *audiobufsize - totalbytes;
_SlibDebug(_DEBUG_, printf("SaDecompress() in totalbytes=%d\n",
totalbytes) );
status = SaDecompress(Info->Sah, NULL, 0,
(unsigned char *)audiobuf+totalbytes, &bytes);
_SlibDebug(_DEBUG_, printf("SaDecompress() out, %d bytes\n",
bytes) );
totalbytes += bytes;
if (Info->AudioTimeStamp!=startaudiotime)
{
startaudiotime=Info->AudioTimeStamp;
bytes_since_timeupdate=bytes;
}
else
bytes_since_timeupdate+=bytes;
}
}
/*
** NOTE: The semantics are different here
** we return the size of just one stereo pair's buffer
*/
*audiobufsize = totalbytes;
_SlibDebug(_WARN_>1 && totalbytes>0 &&
totalbytes!=*audiobufsize,
printf("SlibReadAudio(audiobufsize=%d bytes) totalbytes=%d\n",
*audiobufsize, totalbytes) );
}
break;
#endif /* AC3_SUPPORT */
#ifdef G723_SUPPORT
case SLIB_TYPE_G723:
//G723 decompresses in multiples of 480 samples.
//To eliminate cumbersome buffer calculations,
// Always fill the output buffer up to multiples
// of 480 samples.To do this we iterate basically
// the below "while" loop "audiobufsize/480 times.
{
int iTimes = (int)*audiobufsize/480;
int iLoop =0;
unsigned dword bytes;
if (slibInSyncMode(Info))
{
/* in synchronous mode we can't decompress past last frame
* otherwise we may lose a frame
*/
int iMaxTimes=(int)(slibDataOnPin(Info, SLIB_DATA_COMPRESSED)+
slibDataOnPin(Info, SLIB_DATA_AUDIO))/
SlibGetParamInt(handle, stream, SLIB_PARAM_MININPUTSIZE);
if (iTimes>iMaxTimes)
iTimes=iMaxTimes;
}
while (status==SaErrorNone && iLoop<iTimes)
{
bytes = *audiobufsize - totalbytes;
_SlibDebug(_DEBUG_, printf("SaDecompress() in totalbytes=%d\n",
totalbytes) );
status = SaDecompress(Info->Sah, NULL, 0,
(unsigned char *)audiobuf+totalbytes, &bytes);
_SlibDebug(_DEBUG_, printf("SaDecompress() out, %d bytes\n",
bytes) );
totalbytes += bytes;
iLoop++;
if (Info->AudioTimeStamp!=startaudiotime)
{
startaudiotime=Info->AudioTimeStamp;
bytes_since_timeupdate=bytes;
}
else
bytes_since_timeupdate+=bytes;
}
*audiobufsize = totalbytes;
_SlibDebug(_WARN_>1 && totalbytes>0 &&
totalbytes!=*audiobufsize,
printf("SlibReadAudio(audiobufsize=%d bytes) totalbytes=%d\n",
*audiobufsize, totalbytes) );
}
break;
#endif /* G723_SUPPORT */
default:
*audiobufsize = 0;
return(SlibErrorUnsupportedFormat);
}
/* as we're decompressing audiotime may be updated with timecodes */
if (Info->AudioTimeStamp==startaudiotime)
Info->AudioTimeStamp = startaudiotime + (bytes_since_timeupdate*8000)/
(Info->SamplesPerSec*Info->BitsPerSample*Info->Channels);
_SlibDebug(_TIMECODE_||_VERBOSE_,
calcaudiotime += (*audiobufsize*8000)/
(Info->SamplesPerSec*Info->BitsPerSample*Info->Channels);
printf("AudioTimeStamp=%ld calcaudiotime=%ld (diff=%ld)\n",
Info->AudioTimeStamp, calcaudiotime,
calcaudiotime-Info->AudioTimeStamp);
Info->AudioTimeStamp = calcaudiotime );
_SlibDebug(_VERBOSE_||_TIMECODE_,
printf("ReadAudio(%d) Time=%ld SamplesPerSec=%d BitsPerSample=%d Channels=%d\n",
totalbytes,
Info->AudioTimeStamp, Info->SamplesPerSec, Info->BitsPerSample,
Info->Channels) );
/* Info->SystemTimeStamp=Info->AudioTimeStamp; */
if (status==SaErrorNone)
return(SlibErrorNone);
else if (status==ScErrorEndBitstream || status==ScErrorEOI)
{
if (*audiobufsize!=0)
return(SlibErrorNone);
else
return(SlibErrorEndOfStream);
}
else
{
_SlibDebug(_WARN_ && status!=ScErrorEndBitstream
&& status!=ScErrorEOI,
printf("SlibReadAudio() %s\n", ScGetErrorStr(status)) );
if (SlibIsEnd(handle, stream))
return(SlibErrorEndOfStream);
return(SlibErrorReading);
}
}
SlibStatus_t SlibWriteVideo(SlibHandle_t handle, SlibStream_t stream,
void *videobuf, unsigned dword videobufsize)
{
int compsize=0;
SlibInfo_t *Info=(SlibInfo_t *)handle;
SvStatus_t status;
_SlibDebug(_DEBUG_, printf("SlibWriteVideo()\n") );
if (!handle)
return(SlibErrorBadHandle);
if (!videobuf)
return(SlibErrorBadArgument);
if (videobufsize<(unsigned dword)Info->ImageSize)
return(SlibErrorBufSize);
if (Info->Mode!=SLIB_MODE_COMPRESS)
return(SlibErrorBadMode);
if (Info->VideoFormat==NULL || Info->CompVideoFormat==NULL)
return(SlibErrorUnsupportedFormat);
if (Info->IOError)
return(SlibErrorWriting);
if ((status=slibStartVideo(Info, FALSE))!=SlibErrorNone)
return(status);
if (Info->Sch==NULL) /* start the format converter */
{
if (SconOpen(&Info->Sch, SCON_MODE_VIDEO, (void *)Info->VideoFormat, (void *)Info->CodecVideoFormat)
!=SconErrorNone)
return(SlibErrorUnsupportedFormat);
}
if (!SconIsSame(Info->Sch)) /* need a conversion */
{
unsigned char *tmpbuf=NULL;
if (Info->CodecImagebuf==NULL &&
(Info->CodecImagebuf=SlibAllocBuffer(Info->CodecImageSize))==NULL)
return(SlibErrorMemory);
if (SconConvert(Info->Sch, videobuf, Info->ImageSize,
Info->CodecImagebuf, Info->CodecImageSize) != SconErrorNone)
return(SlibErrorUnsupportedFormat);
videobuf=Info->CodecImagebuf;
videobufsize=Info->CodecImageSize;
}
switch(Info->Type)
{
#ifdef H261_SUPPORT
case SLIB_TYPE_H261:
status = SvCompress(Info->Svh, NULL, 0, videobuf, videobufsize, &compsize);
break;
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
case SLIB_TYPE_H263:
status = SvCompress(Info->Svh, NULL, 0, videobuf, videobufsize, &compsize);
break;
#endif /* H263_SUPPORT */
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_VIDEO:
case SLIB_TYPE_MPEG2_VIDEO:
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
status = SvCompress(Info->Svh, NULL, 0, videobuf, videobufsize, &compsize);
break;
#endif /* MPEG_SUPPORT */
#ifdef HUFF_SUPPORT
case SLIB_TYPE_SHUFF:
status = SvCompress(Info->Svh, NULL, 0, videobuf, videobufsize, &compsize);
break;
#endif /* HUFF_SUPPORT */
default:
return(SlibErrorUnsupportedFormat);
}
if (status==SvErrorNone && !Info->IOError)
{
if (Info->stats && Info->stats->Record)
Info->stats->FramesProcessed++;
slibAdvancePositions(Info, 1);
}
else
{
_SlibDebug(_WARN_, printf("SlibWriteVideo() %s\n",
ScGetErrorStr(status)) );
if (status==ScErrorEndBitstream || Info->IOError)
return(SlibErrorEndOfStream);
return(SlibErrorWriting);
}
return(SlibErrorNone);
}
SlibStatus_t SlibWriteAudio(SlibHandle_t handle, SlibStream_t stream,
void *audiobuf, unsigned dword audiobufsize)
{
unsigned dword compsize=0;
SlibInfo_t *Info=(SlibInfo_t *)handle;
SvStatus_t status;
_SlibDebug(_DEBUG_, printf("SlibAudioVideo()\n") );
if (!handle)
return(SlibErrorBadHandle);
if (!audiobuf)
return(SlibErrorBadArgument);
if (Info->Mode!=SLIB_MODE_COMPRESS)
return(SlibErrorBadMode);
if (Info->AudioFormat==NULL || Info->CompAudioFormat==NULL)
{
_SlibDebug(_VERBOSE_ || _WARN_,
printf("SlibWriteAudio() Audio Formats not setup\n") );
return(SlibErrorUnsupportedFormat);
}
if (Info->IOError)
return(SlibErrorWriting);
if ((status=slibStartAudio(Info))!=SlibErrorNone)
return(status);
switch(Info->Type)
{
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_AUDIO:
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
{
unsigned dword audiobytes;
void *audiooutbuf=NULL;
status=slibConvertAudio(Info, audiobuf, audiobufsize,
Info->SamplesPerSec, Info->BitsPerSample,
&audiooutbuf, &audiobytes,
Info->AudioFormat->nSamplesPerSec,
Info->AudioFormat->wBitsPerSample,
Info->Channels);
if (status!=SlibErrorNone)
return(status);
audiobuf=audiooutbuf;
audiobufsize=audiobytes;
if (Info->AudiobufUsed && Info->Audiobuf) /* left over audio data */
{
if (Info->AudiobufSize<Info->AudiobufUsed+audiobufsize)
{
unsigned char *newbuf;
/* enlarge Audiobuf */
_SlibDebug(_DEBUG_, printf("enlarging Audiobuf: %d->%d bytes\n",
Info->AudiobufSize,audiobufsize+4608) );
newbuf=SlibAllocBuffer(audiobufsize+4608);
if (!newbuf)
return(SlibErrorMemory);
memcpy(newbuf, Info->Audiobuf, Info->AudiobufUsed);
SlibFreeBuffer(Info->Audiobuf);
Info->AudiobufSize+=audiobufsize;
Info->Audiobuf=newbuf;
}
_SlibDebug(_DEBUG_,
printf("Appending audio data: Info->AudiobufUsed=%d\n",
Info->AudiobufUsed) );
memcpy(Info->Audiobuf+Info->AudiobufUsed, audiobuf, audiobufsize);
audiobuf=Info->Audiobuf;
audiobufsize+=Info->AudiobufUsed;
audiobytes=audiobufsize;
Info->AudiobufUsed=0;
}
status = SaCompress(Info->Sah, (unsigned char *)audiobuf,
&audiobytes, NULL, &compsize);
if (audiobytes<audiobufsize) /* save audio data not compressed */
{
_SlibDebug(_DEBUG_,
printf("audiobytes(%d)<audiobufsize(%d)\n",
audiobytes,audiobufsize) );
if (!Info->Audiobuf)
{
Info->AudiobufSize=audiobufsize+(audiobufsize-audiobytes);
Info->Audiobuf=SlibAllocBuffer(Info->AudiobufSize);
if (!Info->Audiobuf)
{
Info->AudiobufSize=0;
return(SlibErrorMemory);
}
}
memcpy(Info->Audiobuf, (unsigned char *)audiobuf+audiobytes,
audiobufsize-audiobytes);
Info->AudiobufUsed=audiobufsize-audiobytes;
}
audiobufsize=audiobytes; /* actual amount written */
if (audiooutbuf)
SlibFreeBuffer(audiooutbuf);
}
break;
#endif /* MPEG_SUPPORT */
#ifdef G723_SUPPORT
case SLIB_TYPE_G723:
{
unsigned int iNumBytesUnProcessed =0;
unsigned int iNumBytesCompressed = 0;
//You always compress in terms of frames (Frame is 480 bytes)
//So,the files with sizes which are not exactly divisible by
// 480 always leave some bytes at the end Unprocessed,Which is O.K
//Check for any Unprocessed Audio stored in Temp buff
//from the previous call to SlibWriteAudio.
if (Info->AudiobufUsed && Info->Audiobuf) /* left over audio data */
{
if (Info->AudiobufSize < Info->AudiobufUsed+audiobufsize)
{
unsigned char *newbuf;
/* enlarge Audiobuf to new Size (Current size + left over audio)*/
_SlibDebug(_DEBUG_, printf("enlarging Audiobuf: %d->%d bytes\n",
Info->AudiobufSize,audiobufsize+Info->AudiobufUsed) );
newbuf=SlibAllocBuffer(Info->AudiobufUsed+audiobufsize);
if (!newbuf)
return(SlibErrorMemory);
memcpy(newbuf, Info->Audiobuf, Info->AudiobufUsed);
SlibFreeBuffer(Info->Audiobuf);
//Info->AudiobufSize+=audiobufsize;
Info->Audiobuf=newbuf;
}
_SlibDebug(_DEBUG_,
printf("Appending audio data: Info->AudiobufUsed=%d\n",
Info->AudiobufUsed) );
memcpy(Info->Audiobuf+Info->AudiobufUsed, audiobuf, audiobufsize);
audiobuf=Info->Audiobuf;
audiobufsize+=Info->AudiobufUsed;
Info->AudiobufUsed=0;
}
iNumBytesCompressed = audiobufsize;
status = SaCompress(Info->Sah,(unsigned char *)audiobuf,
&iNumBytesCompressed, NULL,&compsize);
iNumBytesUnProcessed = audiobufsize - iNumBytesCompressed;
//Store the Unprocessed Bytes into temp buffer
if(iNumBytesUnProcessed)
{
//Allocate temp buff and store this audio.
if (!Info->Audiobuf)
{
//MVP:To reduce ReAllocations and copying of memory
//while checking for Unprocessed data (above),Allocate
// now (normal audio buff size + Unprocessed bytes) more
// memory upfront.
Info->AudiobufSize=audiobufsize + iNumBytesUnProcessed;
Info->Audiobuf=SlibAllocBuffer(Info->AudiobufSize);
if (!Info->Audiobuf)
{
Info->AudiobufSize=0;
return(SlibErrorMemory);
}
}
memcpy(Info->Audiobuf, (unsigned char *)audiobuf+iNumBytesCompressed,
iNumBytesUnProcessed);
Info->AudiobufUsed=iNumBytesUnProcessed;
}
audiobufsize=iNumBytesCompressed; /* actual amount written */
}
break;
#endif /* G723_SUPPORT */
default:
_SlibDebug(_VERBOSE_ || _WARN_,
printf("SlibWriteAudio() Unsupported Format\n") );
return(SlibErrorUnsupportedFormat);
}
if (status==SaErrorNone && !Info->IOError)
{
if (Info->AudioFormat)
Info->AudioTimeStamp += (audiobufsize*8000)/
(Info->AudioFormat->nSamplesPerSec*Info->AudioFormat->wBitsPerSample*
Info->Channels);
else
Info->AudioTimeStamp += (audiobufsize*8000)/
(Info->SamplesPerSec*Info->BitsPerSample*Info->Channels);
_SlibDebug(_VERBOSE_||_TIMECODE_,
printf("WriteAudio(%d) Time=%ld SamplesPerSec=%d BitsPerSample=%d Channels=%d\n",
audiobufsize,
Info->AudioTimeStamp, Info->SamplesPerSec, Info->BitsPerSample,
Info->Channels) );
}
else
{
_SlibDebug(_WARN_, printf("SlibWriteAudio() %s\n", ScGetErrorStr(status)) );
if (status==ScErrorEndBitstream || Info->IOError)
return(SlibErrorEndOfStream);
return(SlibErrorWriting);
}
return(SlibErrorNone);
}
/*
** Name: slibPinReposition
** Purpose: Called when input data stream is to be repositioned.
*/
SlibStatus_t slibReposition(SlibInfo_t *Info, SlibPosition_t position)
{
SlibPin_t *pin=slibGetPin(Info, SLIB_DATA_COMPRESSED);
_SlibDebug(_DEBUG_, printf("slibReposition() VideoCodecState=%d\n",
Info->VideoCodecState));
if (pin) pin->Offset=position;
Info->VideoPTimeCode = SLIB_TIME_NONE;
Info->VideoDTimeCode = SLIB_TIME_NONE;
Info->AudioPTimeCode = SLIB_TIME_NONE;
Info->AudioDTimeCode = SLIB_TIME_NONE;
if (Info->Fd >= 0)
{
_SlibDebug(_SEEK_, printf("ScFileSeek(%d, %d)\n", Info->Fd, position) );
if (ScFileSeek(Info->Fd, position)!=NoErrors)
return(SlibErrorEndOfStream);
return(SlibErrorNone);
}
else if (Info->SlibCB)
{
SlibMessage_t result;
_SlibDebug(_VERBOSE_,
printf("slibReposition() SlibCB(SLIB_MSG_REPOSITION, %d)\n",
position) );
result=(*(Info->SlibCB))((SlibHandle_t)Info,
SLIB_MSG_REPOSITION, (SlibCBParam1_t)position,
(SlibCBParam2_t)0, (void *)Info->SlibCBUserData);
if (result!=SLIB_MSG_CONTINUE)
return(SlibErrorEndOfStream);
return(SlibErrorNone);
}
return(SlibErrorForwardOnly);
}
/*
** Name: slibPinPrepareReposition
** Purpose: Should be called when a stream is about to be repositioned (a seek).
** This will empty any remaining buffers being used by the
** CODECs and restart them.
*/
void slibPinPrepareReposition(SlibInfo_t *Info, int pinid)
{
_SlibDebug(_DEBUG_, printf("slibPinPrepareReposition() VideoCodecState=%d\n",
Info->VideoCodecState));
switch(pinid)
{
case SLIB_DATA_VIDEO:
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("slibPinPrepareReposition(Video) in\n") );
if (Info->VideoCodecState==SLIB_CODEC_STATE_BEGUN && Info->Svh &&
#ifdef JPEG_SUPPORT
Info->Type != SLIB_TYPE_JPEG_AVI &&
Info->Type != SLIB_TYPE_MJPG_AVI &&
#endif /* JPEG_SUPPORT */
Info->Type != SLIB_TYPE_YUV_AVI)
{
SvDecompressEnd(Info->Svh); /* this will reset the bitstream */
Info->VideoCodecState=SLIB_CODEC_STATE_REPOSITIONING;
_SlibDebug(_DEBUG_, printf("VideoCodecState=REPOSITIONING\n"));
Info->IOError=FALSE;
}
Info->VideoPTimeCode = SLIB_TIME_NONE;
Info->VideoDTimeCode = SLIB_TIME_NONE;
Info->VideoTimeStamp = SLIB_TIME_NONE;
Info->AvgVideoTimeDiff = 0;
Info->VarVideoTimeDiff = 0;
Info->VideoFramesProcessed=0; /* reset frames processed */
break;
case SLIB_DATA_AUDIO:
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("slibPinPrepareReposition(Audio) in\n") );
if (Info->AudioCodecState==SLIB_CODEC_STATE_BEGUN && Info->Sah)
{
SaDecompressEnd(Info->Sah); /* this will reset the bitstream */
Info->AudioCodecState=SLIB_CODEC_STATE_REPOSITIONING;
_SlibDebug(_DEBUG_, printf("AudioCodecState=REPOSITIONING\n"));
Info->IOError=FALSE;
}
Info->AudioPTimeCode = SLIB_TIME_NONE;
Info->AudioDTimeCode = SLIB_TIME_NONE;
Info->AudioTimeStamp = SLIB_TIME_NONE;
break;
default:
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("slibPinPrepareReposition(%d) in\n", pinid) );
}
_SlibDebug(_VERBOSE_||_SEEK_>1, printf("slibPinPrepareReposition(%d) out\n",
pinid) );
}
void slibPinFinishReposition(SlibInfo_t *Info, int pinid)
{
_SlibDebug(_DEBUG_, printf("slibPinFinishReposition() VideoCodecState=%d\n",
Info->VideoCodecState));
switch(pinid)
{
case SLIB_DATA_VIDEO:
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("slibPinFinishReposition(Video) in\n") );
if (Info->VideoCodecState==SLIB_CODEC_STATE_REPOSITIONING &&
Info->Svh && slibGetPin(Info, SLIB_DATA_VIDEO) &&
#ifdef JPEG_SUPPORT
Info->Type != SLIB_TYPE_JPEG_AVI &&
Info->Type != SLIB_TYPE_MJPG_AVI &&
#endif /* JPEG_SUPPORT */
Info->Type != SLIB_TYPE_YUV_AVI)
slibStartVideo(Info, FALSE);
break;
case SLIB_DATA_AUDIO:
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("slibPinFinishReposition(Audio) in\n") );
if (Info->AudioCodecState==SLIB_CODEC_STATE_REPOSITIONING &&
Info->Sah && slibGetPin(Info, SLIB_DATA_AUDIO))
slibStartAudio(Info);
break;
default:
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("slibPinFinishReposition(%d) in\n", pinid) );
}
_SlibDebug(_VERBOSE_||_SEEK_>1, printf("slibPinFinishReposition(%d) out\n",
pinid) );
}
SlibBoolean_t slibUpdateLengths(SlibInfo_t *Info)
{
if (Info->FileSize>0 && !Info->VideoLengthKnown &&
(SlibTimeIsValid(Info->VideoPTimeCode) ||
SvGetParamInt(Info->Svh, SV_PARAM_CALCTIMECODE)>=1000)
)
{
if (Info->VideoTimeStamp>Info->VideoLength)
Info->VideoLength=Info->VideoTimeStamp;
Info->VideoLengthKnown=TRUE;
_SlibDebug(_SEEK_ || _TIMECODE_,
printf("slibUpdateLengths() AudioLength=%ld VideoLength=%ld\n",
Info->AudioLength, Info->VideoLength) );
return(TRUE);
}
return(FALSE);
}
SlibBoolean_t slibUpdatePositions(SlibInfo_t *Info, SlibBoolean_t exactonly)
{
SlibBoolean_t updated=FALSE;
if (!exactonly)
{
if (SlibTimeIsValid(Info->VideoTimeStamp))
updated=TRUE;
else if (SlibTimeIsValid(Info->AudioTimeStamp))
{
if (slibHasVideo(Info))
Info->VideoTimeStamp=Info->AudioTimeStamp;
updated=TRUE;
}
else if (slibHasVideo(Info))
{
Info->VideoTimeStamp=slibGetNextTimeOnPin(Info, slibGetPin(Info, SLIB_DATA_VIDEO), 500*1024);
if (SlibTimeIsValid(Info->VideoTimeStamp))
{
Info->VideoTimeStamp-=Info->VideoPTimeBase;
updated=TRUE;
}
}
}
if (!updated && (!exactonly || SlibTimeIsInValid(Info->VideoPTimeBase)) &&
SvGetParamInt(Info->Svh, SV_PARAM_CALCTIMECODE)>=1500 &&
SvGetParamInt(Info->Svh, SV_PARAM_FRAME)>24)
{
_SlibDebug(_TIMECODE_, printf("slibUpdatePositions() using video time\n") );
Info->VideoTimeStamp=SvGetParamInt(Info->Svh, SV_PARAM_CALCTIMECODE);
updated=TRUE;
}
if (updated)
{
if (Info->VideoTimeStamp>Info->VideoLength)
Info->VideoLength=Info->VideoTimeStamp;
if (SlibTimeIsInValid(Info->AudioTimeStamp) && slibHasAudio(Info))
{
/* need to update audio time */
Info->AudioTimeStamp=slibGetNextTimeOnPin(Info, slibGetPin(Info, SLIB_DATA_AUDIO), 100*1024);
if (SlibTimeIsInValid(Info->AudioTimeStamp))
Info->AudioTimeStamp=Info->VideoTimeStamp;
else
Info->AudioTimeStamp-=Info->AudioPTimeBase;
}
if (SlibTimeIsInValid(Info->VideoPTimeCode))
Info->VideoFramesProcessed=slibTimeToFrame(Info, Info->VideoTimeStamp);
}
_SlibDebug(_SEEK_ || _TIMECODE_,
printf("slibUpdatePositions() AudioTimeStamp=%ld VideoTimeStamp=%ld %s\n",
Info->AudioTimeStamp, Info->VideoTimeStamp, updated?"updated":"") );
return(updated);
}
void slibAdvancePositions(SlibInfo_t *Info, qword frames)
{
Info->VideoFramesProcessed+=frames;
if (Info->FramesPerSec)
{
if (Info->Mode==SLIB_MODE_COMPRESS ||
SlibTimeIsInValid(Info->VideoPTimeCode))
Info->VideoTimeStamp=slibFrameToTime(Info, Info->VideoFramesProcessed);
else
Info->VideoTimeStamp=Info->VideoPTimeCode - Info->VideoPTimeBase +
slibFrameToTime(Info, Info->VideoFramesProcessed);
/* Info->VideoTimeStamp+=slibFrameToTime(Info, frames); */
if (Info->VideoTimeStamp>Info->VideoLength)
Info->VideoLength=Info->VideoTimeStamp;
_SlibDebug(_TIMECODE_,
printf("slibAdvancePositions(frames=%d) VideoTimeStamp=%ld\n",
frames, Info->VideoTimeStamp) );
}
}
SlibStatus_t SlibSeek(SlibHandle_t handle, SlibStream_t stream,
SlibSeekType_t seektype, SlibPosition_t frame)
{
return(SlibSeekEx(handle, stream, seektype, frame, SLIB_UNIT_FRAMES, NULL));
}
SlibStatus_t SlibSeekEx(SlibHandle_t handle, SlibStream_t stream,
SlibSeekType_t seektype, SlibPosition_t seekpos,
SlibUnit_t seekunits, SlibSeekInfo_t *seekinfo)
{
SlibInfo_t *Info=(SlibInfo_t *)handle;
SvStatus_t status=SlibErrorNone;
SlibTime_t seektime, timediff;
unsigned int tries=0;
_SlibDebug(_SEEK_,
printf("SlibSeekEx(stream=%d,seektype=%d,pos=%ld,units=%d)\n",
stream,seektype,seekpos,seekunits) );
if (!handle)
return(SlibErrorBadHandle);
if (Info->Mode!=SLIB_MODE_DECOMPRESS && seektype!=SLIB_SEEK_RESET)
return(SlibErrorBadMode);
if (SlibSeekTypeUsesPosition(seektype))
{
switch (seekunits)
{
case SLIB_UNIT_FRAMES: /* frames */
/* we need to convert the frame to the time */
if (Info->FramesPerSec)
seektime=slibFrameToTime(Info, seekpos);
else
seektime=SLIB_TIME_NONE;
break;
case SLIB_UNIT_MS: /* milliseconds */
seektime=(seekpos<0) ? 0 : seekpos;
break;
case SLIB_UNIT_PERCENT100: /* 100th of a percent */
if (seekpos<0 || seekpos>10000)
return(SlibErrorBadPosition);
if (Info->VideoStreams==0 || stream==SLIB_STREAM_MAINAUDIO)
seektime=(seekpos * Info->AudioLength)/(SlibPosition_t)10000;
else
seektime=(seekpos * Info->VideoLength)/(SlibPosition_t)10000;
break;
default:
return(SlibErrorBadUnit);
}
/* see if the new position is past the end of the file */
if (Info->VideoLengthKnown && seektime>Info->VideoLength)
return(SlibErrorBadPosition);
}
else
seektime=(seekpos<0) ? 0 : seekpos;
if (seekinfo)
seekinfo->FramesSkipped=0;
switch(seektype)
{
case SLIB_SEEK_AHEAD:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,AHEAD,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if (seektime<=0)
return(SlibErrorNone);
if (stream==SLIB_STREAM_MAINAUDIO || Info->VideoStreams<=0)
seektime+=Info->AudioTimeStamp;
else
seektime+=Info->VideoTimeStamp;
return(SlibSeekEx(handle, stream, SLIB_SEEK_NEXT_NEAR, seektime,
SLIB_UNIT_MS, seekinfo));
case SLIB_SEEK_NEXT_NEAR:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,NEXT_NEAR,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
status=slibStartVideo(Info, FALSE);
if (status==SlibErrorNone)
{
qword framesskipped=0;
SlibBoolean_t atkey=FALSE; /* key's must be decoded */
if (Info->Svh) /* update key spacing */
{
Info->KeySpacing=(int)SvGetParamInt(Info->Svh,
SV_PARAM_KEYSPACING);
Info->SubKeySpacing=(int)SvGetParamInt(Info->Svh,
SV_PARAM_SUBKEYSPACING);
}
timediff=seektime-Info->VideoTimeStamp;
while (status==SlibErrorNone &&
(timediff>500 ||
timediff>(Info->VideoFrameDuration*Info->KeySpacing*6)/1000))
{
status=SlibSeekEx(handle, stream, SLIB_SEEK_NEXT_KEY, 0,
SLIB_UNIT_NONE, seekinfo);
if (seekinfo) framesskipped+=seekinfo->FramesSkipped;
timediff=seektime-Info->VideoTimeStamp;
atkey=TRUE;
}
if (!atkey && status==SlibErrorNone &&
(timediff>150 ||
timediff>(Info->VideoFrameDuration*Info->SubKeySpacing*6)/1000))
{
if (SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)!=FRAME_TYPE_I &&
SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)!=FRAME_TYPE_P)
{
/* we're seeking past more than one frame */
status=SlibSeekEx(handle, stream, SLIB_SEEK_NEXT_SUBKEY, 0,
SLIB_UNIT_NONE, seekinfo);
if (seekinfo) framesskipped+=seekinfo->FramesSkipped;
timediff=seektime-Info->VideoTimeStamp;
}
atkey=TRUE;
}
while (!atkey && status==SlibErrorNone &&
timediff>Info->VideoFrameDuration/100)
{
if (SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)==FRAME_TYPE_B ||
SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)==FRAME_TYPE_NONE)
{
/* we can skip B frames without decompressing them */
status=SlibSeekEx(handle, stream, SLIB_SEEK_NEXT, 0,
SLIB_UNIT_NONE, seekinfo);
if (seekinfo) framesskipped+=seekinfo->FramesSkipped;
timediff=seektime-Info->VideoTimeStamp;
}
else
atkey=TRUE;
}
if (seekinfo) seekinfo->FramesSkipped=framesskipped;
}
return(status);
case SLIB_SEEK_NEXT:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,NEXT,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if ((status=slibStartVideo(Info, FALSE))!=SlibErrorNone)
return(status);
#ifdef MPEG_SUPPORT
if (Info->VideoCodecState==SLIB_CODEC_STATE_BEGUN
&& Info->Svh && SlibTypeIsMPEGVideo(Info->Type))
{
SvPictureInfo_t mpegPictureInfo;
unsigned char *videobuf;
/* cannot skip I or B frames without decompressing them */
if (SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)==FRAME_TYPE_I ||
SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)==FRAME_TYPE_P)
{
_SlibDebug(_DEBUG_||_SEEK_, printf("SvDecompressMPEG()\n") );
status = SvDecompressMPEG(Info->Svh, Info->Multibuf,
Info->MultibufSize, &videobuf);
_SlibDebug(_WARN_ && status!=SvErrorNone,
printf("SvDecompressMPEG() %s\n", ScGetErrorStr(status)) );
}
else
{
mpegPictureInfo.Type = SV_I_PICTURE|SV_P_PICTURE|SV_B_PICTURE;
_SlibDebug(_VERBOSE_||_SEEK_>1,
printf("SvFindNextPicture(I|P|B)\n") );
status = SvFindNextPicture(Info->Svh, &mpegPictureInfo);
_SlibDebug(_WARN_ && status!=SvErrorNone,
printf("SvFindNextPicture() %s\n", ScGetErrorStr(status)) );
}
if (status==NoErrors)
{
slibAdvancePositions(Info, 1);
if (Info->stats && Info->stats->Record)
Info->stats->FramesSkipped++;
if (seekinfo) seekinfo->FramesSkipped++;
}
else if (status==ScErrorEndBitstream)
{
if (Info->FileSize>0 && !Info->VideoLengthKnown)
slibUpdateLengths(Info);
return(SlibErrorEndOfStream);
}
return(SlibErrorNone);
}
#endif /* MPEG_SUPPORT */
return(SlibErrorReading);
case SLIB_SEEK_EXACT:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,EXACT,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if (Info->FileSize<=0)
return(SlibErrorFileSize);
if (seektime==0 || Info->VideoStreams<=0)
return(SlibSeekEx(handle, stream, SLIB_SEEK_KEY, 0, SLIB_UNIT_MS,
seekinfo));
timediff=seektime-Info->VideoTimeStamp;
if ((stream==SLIB_STREAM_MAINVIDEO || Info->AudioStreams==0) &&
(timediff>=-20 && timediff<=20)) /* we're already near the frame */
return(SlibErrorNone);
if (Info->Svh) /* update key spacing */
Info->KeySpacing=(int)SvGetParamInt(Info->Svh, SV_PARAM_KEYSPACING);
if (timediff>(Info->KeySpacing*Info->VideoFrameDuration)/100 ||
timediff<0 ||
(stream!=SLIB_STREAM_MAINVIDEO && Info->AudioStreams>0))
{
if (Info->KeySpacing>1)
{
const SlibTime_t keytime=
(Info->VideoFrameDuration*Info->KeySpacing)/100;
if (seektime>=0 && seektime<keytime)
status=SlibSeekEx(handle, stream, SLIB_SEEK_KEY, 0,
SLIB_UNIT_MS, seekinfo);
else
status=SlibSeekEx(handle, stream, SLIB_SEEK_KEY,
seektime-(keytime*2), SLIB_UNIT_MS, seekinfo);
}
else
status=SlibSeekEx(handle, stream, SLIB_SEEK_KEY,
seektime-1000, SLIB_UNIT_MS, seekinfo);
if (status!=NoErrors) return(status);
timediff=seektime-Info->VideoTimeStamp;
}
#if 0
if (SvGetParamFloat(Info->Svh, SV_PARAM_FPS)>0)
Info->FramesPerSec=SvGetParamFloat(Info->Svh, SV_PARAM_FPS);
#endif
if (status==SlibErrorNone && timediff>=Info->VideoFrameDuration/100)
{
dword framesskipped=0;
do {
status=SlibSeekEx(handle, stream, SLIB_SEEK_NEXT, 0,
SLIB_UNIT_NONE, seekinfo);
framesskipped++;
timediff=seektime-Info->VideoTimeStamp;
} while (timediff>0 && status==SlibErrorNone);
if (seekinfo) seekinfo->FramesSkipped+=framesskipped;
/* if we skipped some frames, skip some audio too */
if (framesskipped>5 && stream==SLIB_STREAM_ALL &&
Info->AudioStreams>0)
{
slibPinPrepareReposition(Info, SLIB_DATA_AUDIO);
slibSkipAudio(Info, stream, (Info->VideoFrameDuration*
framesskipped)/100);
slibPinFinishReposition(Info, SLIB_DATA_AUDIO);
}
}
return(status);
case SLIB_SEEK_NEXT_KEY:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,NEXT_KEY,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if ((status=slibStartVideo(Info, FALSE))!=SlibErrorNone)
return(status);
#ifdef MPEG_SUPPORT
if (Info->Svh && SlibTypeIsMPEGVideo(Info->Type))
{
SvPictureInfo_t mpegPictureInfo;
SlibTime_t vtime=Info->VideoTimeStamp;
do {
mpegPictureInfo.Type = SV_I_PICTURE;
status = SvFindNextPicture(Info->Svh, &mpegPictureInfo);
if (status==NoErrors && mpegPictureInfo.Type==SV_I_PICTURE)
{
if (Info->stats && Info->stats->Record)
Info->stats->FramesSkipped+=mpegPictureInfo.TemporalRef;
if (vtime==Info->VideoTimeStamp)
/* timecode didn't update time */
slibAdvancePositions(Info, mpegPictureInfo.TemporalRef);
vtime=Info->VideoTimeStamp;
if (seekinfo)
{
seekinfo->FramesSkipped+=mpegPictureInfo.TemporalRef;
seekinfo->VideoTimeStamp=Info->VideoTimeStamp;
seekinfo->AudioTimeStamp=Info->AudioTimeStamp;
}
return(SlibErrorNone);
}
} while (status==NoErrors);
if (seekinfo)
{
seekinfo->VideoTimeStamp=Info->VideoTimeStamp;
seekinfo->AudioTimeStamp=Info->AudioTimeStamp;
}
if (status==ScErrorEndBitstream)
{
if (Info->FileSize>0 && !Info->VideoLengthKnown)
slibUpdateLengths(Info);
return(SlibErrorEndOfStream);
}
}
_SlibDebug(_WARN_, printf("SvFindNextPicture() %s\n",
ScGetErrorStr(status)) );
#endif /* MPEG_SUPPORT */
/* do an absolute seek */
status=SlibSeekEx(handle, stream, SLIB_SEEK_KEY,
(Info->VideoStreams<=0?Info->AudioTimeStamp
:Info->VideoTimeStamp)+1000,
SLIB_UNIT_MS, seekinfo);
return(status);
case SLIB_SEEK_NEXT_SUBKEY:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,NEXT_SUBKEY,time=%d) VideoTime=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if ((status=slibStartVideo(Info, FALSE))!=SlibErrorNone)
return(status);
#ifdef MPEG_SUPPORT
if (Info->Svh && SlibTypeIsMPEGVideo(Info->Type))
{
SvPictureInfo_t mpegPictureInfo;
unsigned char *videobuf;
SlibTime_t vtime=Info->VideoTimeStamp;
/* cannot skip I or B frames without decompressing them */
if (SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)==FRAME_TYPE_I ||
SvGetParamInt(Info->Svh, SV_PARAM_FRAMETYPE)==FRAME_TYPE_P)
{
_SlibDebug(_DEBUG_||_SEEK_, printf("SvDecompressMPEG()\n") );
status = SvDecompressMPEG(Info->Svh, Info->Multibuf,
Info->MultibufSize, &videobuf);
if (vtime==Info->VideoTimeStamp /* timecode didn't update time */
&& status==SvErrorNone)
slibAdvancePositions(Info, 1);
vtime=Info->VideoTimeStamp;
if (seekinfo)
seekinfo->FramesSkipped+=mpegPictureInfo.TemporalRef;
_SlibDebug(_WARN_ && status!=SvErrorNone,
printf("SvDecompressMPEG() %s\n", ScGetErrorStr(status)) );
}
do {
mpegPictureInfo.Type = SV_I_PICTURE|SV_P_PICTURE;
status = SvFindNextPicture(Info->Svh, &mpegPictureInfo);
if (Info->stats && Info->stats->Record)
Info->stats->FramesSkipped+=mpegPictureInfo.TemporalRef;
if (vtime==Info->VideoTimeStamp) /* timecode didn't update time */
slibAdvancePositions(Info, mpegPictureInfo.TemporalRef);
vtime=Info->VideoTimeStamp;
if (seekinfo)
seekinfo->FramesSkipped+=mpegPictureInfo.TemporalRef;
if (mpegPictureInfo.Type == SV_I_PICTURE ||
mpegPictureInfo.Type == SV_P_PICTURE)
{
/* found a subkey frame */
if (seekinfo)
{
seekinfo->VideoTimeStamp=Info->VideoTimeStamp;
seekinfo->AudioTimeStamp=Info->AudioTimeStamp;
}
return(SlibErrorNone);
}
} while(status==NoErrors);
if (status==ScErrorEndBitstream)
{
if (Info->FileSize>0 && !Info->VideoLengthKnown)
slibUpdateLengths(Info);
if (seekinfo)
{
seekinfo->VideoTimeStamp=Info->VideoTimeStamp;
seekinfo->AudioTimeStamp=Info->AudioTimeStamp;
}
return(SlibErrorEndOfStream);
}
}
_SlibDebug(_WARN_, printf("SvFindNextPicture() %s\n",
ScGetErrorStr(status)) );
#endif /* MPEG_SUPPORT */
/* do an absolute seek */
status=SlibSeekEx(handle, stream, SLIB_SEEK_KEY,
(Info->VideoStreams<=0?Info->AudioTimeStamp
:Info->VideoTimeStamp)+500,
SLIB_UNIT_MS, seekinfo);
return(status);
case SLIB_SEEK_KEY:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,KEY,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if (!Info->HeaderProcessed)
{
/* At very start of file we must Start the codecs since they
* may need crucial header info
*/
status=slibStartVideo(Info, FALSE);
if (status!=SlibErrorNone) return(status);
}
if (Info->FileSize<=0)
return(SlibErrorFileSize);
if (seekpos!=0 && seekunits!=SLIB_UNIT_PERCENT100 &&
(stream==SLIB_STREAM_MAINVIDEO || Info->AudioStreams==0) &&
SlibTimeIsValid(Info->VideoTimeStamp))
{
/* see if we're already near the frame */
timediff=seektime-Info->VideoTimeStamp;
if (timediff>=-33 && timediff<=33)
return(SlibErrorNone);
}
if ((seekunits==SLIB_UNIT_PERCENT100 && seekpos<=50)
|| seektime<=slibTimeToFrame(Info, 6))
{
/* close to beginning */
if (seektime<=(Info->VideoFrameDuration*2)/100 &&
stream==SLIB_STREAM_MAINVIDEO) /* already close enough */
return(SlibErrorNone);
seek_to_beginning:
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibPinPrepareReposition(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibPinPrepareReposition(Info, SLIB_DATA_AUDIO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibEmptyPin(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibEmptyPin(Info, SLIB_DATA_AUDIO);
slibEmptyPin(Info, SLIB_DATA_COMPRESSED);
if ((status=slibReposition(Info, 0))!=SlibErrorNone)
return(status);
Info->IOError=FALSE;
Info->VideoTimeStamp = slibHasVideo(Info) ? 0 : SLIB_TIME_NONE;
Info->AudioTimeStamp = slibHasAudio(Info) ? 0 : SLIB_TIME_NONE;
return(SlibErrorNone);
}
else
{
qword skippedframes=0;
unsigned qword filepos;
SlibTime_t vtime;
const qword length=(Info->VideoStreams<=0) ? Info->AudioLength
: Info->VideoLength;
if (seekunits==SLIB_UNIT_PERCENT100)
{
unsigned qword bytes_between_keys=Info->TotalBitRate/(8*2);
filepos = (seekpos*Info->FileSize)/10000;
/* seek a little before the desired point */
if (bytes_between_keys>filepos)
goto seek_to_beginning;
else
filepos-=bytes_between_keys;
}
else if (length==0)
goto seek_to_beginning;
else if (Info->FileSize<0x100000000)/* be careful of mul overflow */
filepos = (seektime*Info->FileSize)/length;
else
filepos = ((seektime/100)*Info->FileSize)/(length/100);
seek_to_key:
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibPinPrepareReposition(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibPinPrepareReposition(Info, SLIB_DATA_AUDIO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibEmptyPin(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibEmptyPin(Info, SLIB_DATA_AUDIO);
slibEmptyPin(Info, SLIB_DATA_COMPRESSED);
if ((status=slibReposition(Info, filepos))!=SlibErrorNone)
return(status);
Info->IOError=FALSE;
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibPinFinishReposition(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibPinFinishReposition(Info, SLIB_DATA_AUDIO);
vtime=Info->VideoTimeStamp;
#ifdef MPEG_SUPPORT
if (Info->Svh && SlibTypeIsMPEGVideo(Info->Type))
{
SvPictureInfo_t mpegPictureInfo;
if ((status=slibStartVideo(Info, FALSE))!=SlibErrorNone)
return(status);
mpegPictureInfo.Type = SV_I_PICTURE;
status = SvFindNextPicture(Info->Svh, &mpegPictureInfo);
_SlibDebug(_WARN_ && status!=NoErrors,
printf("SvFindNextPicture() %s\n",
ScGetErrorStr(status)) );
if (status!=NoErrors)
return(SlibErrorEndOfStream);
skippedframes=mpegPictureInfo.TemporalRef;
}
#endif /* MPEG_SUPPORT */
if (seekunits==SLIB_UNIT_PERCENT100)
{
/* See if we seeked to far ahead */
SlibPosition_t posdiff=
SlibGetParamInt(Info, SLIB_STREAM_ALL, SLIB_PARAM_PERCENT100)
-seekpos;
if (filepos>0 && posdiff>0 && tries<2)
{
tries++;
/* we're ahead by one percent or more */
/* move filepos back in the proportion that we're off by */
filepos-=(posdiff*Info->FileSize)/8000;
if (filepos<0)
goto seek_to_beginning;
goto seek_to_key;
}
}
if (slibUpdatePositions(Info, FALSE)) /* timecoded */
{
/* timecoded */
/*
* See if we seeked to far ahead
* Note: if times are way off then we should ignore them.
*/
if (seekunits==SLIB_UNIT_PERCENT100) /* ignore times */
timediff=0;
else
{
timediff=seektime-Info->VideoTimeStamp;
if (timediff>-5000 && timediff<-100 && tries<3)
{
/* move filepos back in the proportion that we're off by */
filepos=(filepos*seektime)/Info->VideoTimeStamp;
if (filepos<0)
filepos=0;
tries++;
goto seek_to_key;
}
}
#ifdef MPEG_SUPPORT
if (Info->Svh && SlibTypeIsMPEGVideo(Info->Type))
{
SvPictureInfo_t mpegPictureInfo;
mpegPictureInfo.Type = SV_I_PICTURE;
while (timediff>Info->VideoFrameDuration/100 &&status==NoErrors)
{
_SlibDebug(_SEEK_>1,
printf("SlibSeekEx(KEY, %d) Find next I frame (%d/%d)\n",
seektime, SvGetParamInt(Info->Svh, SV_PARAM_CALCTIMECODE),
Info->VideoTimeStamp) );
status = SvFindNextPicture(Info->Svh, &mpegPictureInfo);
_SlibDebug(_WARN_ && status!=NoErrors,
printf("SvFindNextPicture() %s\n", ScGetErrorStr(status)) );
skippedframes+=mpegPictureInfo.TemporalRef;
if (vtime==Info->VideoTimeStamp)
/* timecode didn't update time */
slibAdvancePositions(Info, mpegPictureInfo.TemporalRef);
vtime=Info->VideoTimeStamp;
timediff=seektime-Info->VideoTimeStamp;
}
}
#endif /* MPEG_SUPPORT */
}
else
{
_SlibDebug(_SEEK_, printf("SlibSeekEx(KEY, %d) no timecode\n",
seektime) );
if (slibHasVideo(Info))
{
Info->VideoTimeStamp=seektime;
Info->VideoFramesProcessed=slibTimeToFrame(Info, seektime);
}
if (slibHasAudio(Info))
Info->AudioTimeStamp=seektime;
slibAdvancePositions(Info, skippedframes);
timediff=seektime-Info->VideoTimeStamp;
}
if (Info->stats && Info->stats->Record)
Info->stats->FramesSkipped+=skippedframes;
if (seekinfo) seekinfo->FramesSkipped=skippedframes;
#if 0
if (Info->Svh)
Info->FramesPerSec=SvGetParamFloat(Info->Svh, SV_PARAM_FPS);
#endif
/* if we skipped some frames, skip some audio too */
if (skippedframes>5 && stream==SLIB_STREAM_ALL && slibHasAudio(Info))
{
slibPinPrepareReposition(Info, SLIB_DATA_AUDIO);
slibSkipAudio(Info, stream, (Info->VideoFrameDuration*
skippedframes)/100);
slibPinFinishReposition(Info, SLIB_DATA_AUDIO);
if (SlibTimeIsInValid(Info->AudioTimeStamp))
{
Info->AudioTimeStamp=slibGetNextTimeOnPin(Info, slibGetPin(Info, SLIB_DATA_AUDIO), 100*1024);
if (SlibTimeIsInValid(Info->AudioTimeStamp))
Info->AudioTimeStamp=Info->VideoTimeStamp;
else
Info->AudioTimeStamp-=Info->AudioPTimeBase;
}
}
if (status==ScErrorEndBitstream)
{
if (Info->FileSize>0 && !Info->VideoLengthKnown)
slibUpdateLengths(Info);
return(SlibErrorEndOfStream);
}
else if (status!=NoErrors)
return(SlibErrorReading);
return(SlibErrorNone);
}
break;
case SLIB_SEEK_RESET:
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,RESET,time=%d) VideoTimeStamp=%ld\n",
stream,seektime,Info->VideoTimeStamp) );
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibPinPrepareReposition(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibPinPrepareReposition(Info, SLIB_DATA_AUDIO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINVIDEO)
slibEmptyPin(Info, SLIB_DATA_VIDEO);
if (stream==SLIB_STREAM_ALL || stream==SLIB_STREAM_MAINAUDIO)
slibEmptyPin(Info, SLIB_DATA_AUDIO);
if (stream==SLIB_STREAM_MAINAUDIO)
slibPinFinishReposition(Info, SLIB_DATA_AUDIO);
if (stream==SLIB_STREAM_ALL)
{
slibEmptyPin(Info, SLIB_DATA_COMPRESSED);
Info->BytesProcessed = 0;
}
Info->HeaderProcessed = FALSE;
return(SlibErrorNone);
case SLIB_SEEK_RESYNC:
seekpos=SlibGetParamInt(Info, SLIB_STREAM_ALL, SLIB_PARAM_PERCENT100);
if (seekpos<0 ||
(SlibTimeIsValid(Info->VideoTimeStamp) &&
Info->VideoTimeStamp<slibFrameToTime(Info, 6)))
seekpos=0;
_SlibDebug(_VERBOSE_||_SEEK_,
printf("SlibSeekEx(stream=%d,RESYNC) seekpos=%ld\n",
stream, seekpos) );
return(SlibSeekEx(handle, SLIB_STREAM_ALL, SLIB_SEEK_KEY, seekpos,
SLIB_UNIT_PERCENT100, seekinfo));
default:
_SlibDebug(_VERBOSE_||_SEEK_||_WARN_,
printf("SlibSeekEx(stream=%d,seektype=%d,time=%d) VideoTimeStamp=%ld Bad seek type\n",
stream,seektype,seektime,Info->VideoTimeStamp) );
}
return(SlibErrorForwardOnly);
}
SlibList_t *SlibQueryList(SlibQueryType_t qtype)
{
switch(qtype)
{
case SLIB_QUERY_TYPES: return(_listTypes);
case SLIB_QUERY_COMP_TYPES: return(_listCompressTypes);
case SLIB_QUERY_DECOMP_TYPES: return(_listDecompressTypes);
case SLIB_QUERY_ERRORS: return(_listErrors);
default: return(NULL);
}
}
char *SlibQueryForDesc(SlibQueryType_t qtype, int enumval)
{
SlibList_t *entry=SlibQueryList(qtype);
if (entry)
entry=SlibFindEnumEntry(entry, enumval);
if (entry)
return(entry->Desc);
else
return(NULL);
}
int SlibQueryForEnum(SlibQueryType_t qtype, char *name)
{
SlibList_t *list=SlibQueryList(qtype);
if (!list)
return(-1);
while (list->Name)
{
if (strcmp(list->Name, name)==0)
return(list->Enum);
list++;
}
return(-1);
}
SlibBoolean_t SlibIsEnd(SlibHandle_t handle, SlibStream_t stream)
{
SlibInfo_t *Info=(SlibInfo_t *)handle;
SlibBoolean_t isend=FALSE;
if (!handle)
isend=TRUE;
else if (stream==SLIB_STREAM_MAINAUDIO)
{
isend=SlibPeekBuffer(Info, SLIB_DATA_AUDIO, NULL, NULL)==NULL?TRUE:FALSE;
if (isend && Info->Sah) /* see if the audio codec still has data */
{
ScBitstream_t *bs=SaGetDataSource(Info->Sah);
if (bs && !bs->EOI) isend=FALSE;
}
}
else if (stream==SLIB_STREAM_MAINVIDEO)
{
isend=SlibPeekBuffer(Info, SLIB_DATA_VIDEO, NULL, NULL)==NULL?TRUE:FALSE;
if (isend && Info->Svh) /* see if the video codec still has data */
{
ScBitstream_t *bs=SvGetDataSource(Info->Svh);
if (bs && !bs->EOI) isend=FALSE;
}
}
else if (SlibPeekBuffer(Info, SLIB_DATA_AUDIO, NULL, NULL)==NULL &&
SlibPeekBuffer(Info, SLIB_DATA_VIDEO, NULL, NULL)==NULL &&
SlibPeekBuffer(Info, SLIB_DATA_COMPRESSED, NULL, NULL)==NULL)
{
ScBitstream_t *bs;
isend=TRUE;
if (Info->Svh) /* see if the video codec still has data */
{
bs=SvGetDataSource(Info->Svh);
if (bs && !bs->EOI) isend=FALSE;
}
if (isend && Info->Sah) /* see if the audio codec still has data */
{
bs=SaGetDataSource(Info->Sah);
if (bs && !bs->EOI) isend=FALSE;
}
}
_SlibDebug(_VERBOSE_,
printf("SlibIsEnd() %s\n",isend?"TRUE":"FALSE"));
return(isend);
}
SlibStatus_t SlibClose(SlibHandle_t handle)
{
SlibInfo_t *Info=(SlibInfo_t *)handle;
_SlibDebug(_DEBUG_, printf("SlibClose\n") );
if (!handle)
return(SlibErrorBadHandle);
/* close video codec */
if (Info->Svh)
{
if (Info->VideoCodecState==SLIB_CODEC_STATE_BEGUN)
{
_SlibDebug(_DEBUG_, printf("SvDecompress/CompressEnd()\n") );
if (Info->Mode==SLIB_MODE_DECOMPRESS)
SvDecompressEnd(Info->Svh);
else if (Info->Mode==SLIB_MODE_COMPRESS)
SvCompressEnd(Info->Svh);
Info->VideoCodecState=SLIB_CODEC_STATE_INITED;
}
_SlibDebug(_DEBUG_, printf("SvCloseCodec()\n") );
SvCloseCodec(Info->Svh);
}
Info->VideoCodecState=SLIB_CODEC_STATE_NONE;
/* close audio codec */
if (Info->Sah)
{
if (Info->AudioCodecState==SLIB_CODEC_STATE_BEGUN)
{
if (Info->Mode==SLIB_MODE_DECOMPRESS)
SaDecompressEnd(Info->Sah);
else if (Info->Mode==SLIB_MODE_COMPRESS)
SaCompressEnd(Info->Sah);
Info->AudioCodecState=SLIB_CODEC_STATE_INITED;
}
_SlibDebug(_DEBUG_, printf("SaCloseCodec()\n") );
SaCloseCodec(Info->Sah);
}
Info->AudioCodecState=SLIB_CODEC_STATE_NONE;
if (Info->Mode==SLIB_MODE_COMPRESS && Info->HeaderProcessed)
slibCommitBuffers(Info, TRUE);
/* close format converter */
if (Info->Sch)
{
SconClose(Info->Sch);
Info->Sch=NULL;
}
/* close data sources */
if (Info->Fd>=0)
{
_SlibDebug(_DEBUG_, printf("ScFileClose(%d)\n",Info->Fd) );
ScFileClose(Info->Fd);
Info->Fd=-1;
}
slibRemovePins(Info);
/* slibDumpMemory(); */
if (Info->SlibCB)
{
SlibMessage_t result;
_SlibDebug(_VERBOSE_,
printf("SlibClose() SlibCB(SLIB_MSG_CLOSE)\n") );
result=(*(Info->SlibCB))((SlibHandle_t)Info,
SLIB_MSG_CLOSE, (SlibCBParam1_t)0,
(SlibCBParam2_t)0, (void *)Info->SlibCBUserData);
Info->SlibCB=NULL;
}
/* free memory */
if (Info->stats) ScFree(Info->stats);
if (Info->CompVideoFormat) ScFree(Info->CompVideoFormat);
if (Info->CodecVideoFormat) ScFree(Info->CodecVideoFormat);
if (Info->VideoFormat) ScFree(Info->VideoFormat);
if (Info->AudioFormat) ScFree(Info->AudioFormat);
if (Info->CompAudioFormat) ScFree(Info->CompAudioFormat);
if (Info->Imagebuf) SlibFreeBuffer(Info->Imagebuf);
if (Info->CodecImagebuf) SlibFreeBuffer(Info->CodecImagebuf);
if (Info->IntImagebuf) SlibFreeBuffer(Info->IntImagebuf);
if (Info->Audiobuf) SlibFreeBuffer(Info->Audiobuf);
if (Info->Multibuf) /* free all outstanding allocations on Multibuf */
while (SlibFreeBuffer(Info->Multibuf)==SlibErrorNone);
ScFree(Info);
_SlibDebug(_WARN_ && SlibMemUsed()>0, printf("SlibClose() mem used=%d\n",
SlibMemUsed()) );
return(SlibErrorNone);
}
/*
SlibStatus_t SlibGetInfo(SlibHandle_t handle, SlibInfo_t *info)
{
if (!handle)
return(SlibErrorBadHandle);
if (!info)
return(SlibErrorBadArgument);
memcpy(info, handle, sizeof(SlibInfo_t));
return(SlibErrorNone);
}
*/