summaryrefslogtreecommitdiff
path: root/src/input/vcd/libvcd/mpeg_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/vcd/libvcd/mpeg_stream.c')
-rw-r--r--src/input/vcd/libvcd/mpeg_stream.c487
1 files changed, 0 insertions, 487 deletions
diff --git a/src/input/vcd/libvcd/mpeg_stream.c b/src/input/vcd/libvcd/mpeg_stream.c
deleted file mode 100644
index e5466766a..000000000
--- a/src/input/vcd/libvcd/mpeg_stream.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- $Id: mpeg_stream.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $
-
- Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cdio/cdio.h>
-#include <cdio/bytesex.h>
-
-#include <libvcd/logging.h>
-
-/* Private headers */
-#include "vcd_assert.h"
-#include "mpeg_stream.h"
-#include "data_structures.h"
-#include "mpeg.h"
-#include "util.h"
-
-static const char _rcsid[] = "$Id: mpeg_stream.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $";
-
-struct _VcdMpegSource
-{
- VcdDataSource *data_source;
-
- bool scanned;
-
- /* _get_packet cache */
- unsigned _read_pkt_pos;
- unsigned _read_pkt_no;
-
- struct vcd_mpeg_stream_info info;
-};
-
-/*
- * access functions
- */
-
-VcdMpegSource *
-vcd_mpeg_source_new (VcdDataSource *mpeg_file)
-{
- VcdMpegSource *new_obj;
-
- vcd_assert (mpeg_file != NULL);
-
- new_obj = _vcd_malloc (sizeof (VcdMpegSource));
-
- new_obj->data_source = mpeg_file;
- new_obj->scanned = false;
-
- return new_obj;
-}
-
-void
-vcd_mpeg_source_destroy (VcdMpegSource *obj, bool destroy_file_obj)
-{
- int i;
- vcd_assert (obj != NULL);
-
- if (destroy_file_obj)
- vcd_data_source_destroy (obj->data_source);
-
- for (i = 0; i < 3; i++)
- if (obj->info.shdr[i].aps_list)
- _cdio_list_free (obj->info.shdr[i].aps_list, true);
-
- free (obj);
-}
-
-const struct vcd_mpeg_stream_info *
-vcd_mpeg_source_get_info (VcdMpegSource *obj)
-{
- vcd_assert (obj != NULL);
-
- vcd_assert (obj->scanned);
-
- return &(obj->info);
-}
-
-long
-vcd_mpeg_source_stat (VcdMpegSource *obj)
-{
- vcd_assert (obj != NULL);
- vcd_assert (!obj->scanned);
-
- return obj->info.packets * 2324;
-}
-
-void
-vcd_mpeg_source_scan (VcdMpegSource *obj, bool strict_aps, bool fix_scan_info,
- vcd_mpeg_prog_cb_t callback, void *user_data)
-{
- unsigned length = 0;
- unsigned pos = 0;
- unsigned pno = 0;
- unsigned padbytes = 0;
- unsigned padpackets = 0;
- VcdMpegStreamCtx state;
- CdioListNode *n;
- vcd_mpeg_prog_info_t _progress = { 0, };
-
- vcd_assert (obj != NULL);
-
- if (obj->scanned)
- {
- vcd_debug ("already scanned... not rescanning");
- return;
- }
-
- vcd_assert (!obj->scanned);
-
- memset (&state, 0, sizeof (state));
-
- if (fix_scan_info)
- state.stream.scan_data_warnings = VCD_MPEG_SCAN_DATA_WARNS + 1;
-
- vcd_data_source_seek (obj->data_source, 0);
- length = vcd_data_source_stat (obj->data_source);
-
- if (callback)
- {
- _progress.length = length;
- callback (&_progress, user_data);
- }
-
-
- while (pos < length)
- {
- char buf[2324] = { 0, };
- int read_len = MIN (sizeof (buf), (length - pos));
- int pkt_len;
-
- vcd_data_source_read (obj->data_source, buf, read_len, 1);
-
- pkt_len = vcd_mpeg_parse_packet (buf, read_len, true, &state);
-
- if (!pkt_len)
- {
- if (!pno)
- vcd_error ("input mpeg stream has been deemed invalid -- aborting");
-
- vcd_warn ("bad packet at packet #%d (stream byte offset %d)"
- " -- remaining %d bytes of stream will be ignored",
- pno, pos, length - pos);
-
- pos = length; /* don't fall into assert... */
- break;
- }
-
- if (callback && (pos - _progress.current_pos) > (length / 100))
- {
- _progress.current_pos = pos;
- _progress.current_pack = pno;
- callback (&_progress, user_data);
- }
-
- switch (state.packet.aps)
- {
- case APS_NONE:
- break;
-
- case APS_I:
- case APS_GI:
- if (strict_aps)
- break; /* allow only if now strict aps */
-
- case APS_SGI:
- case APS_ASGI:
- {
- struct aps_data *_data = _vcd_malloc (sizeof (struct aps_data));
-
- _data->packet_no = pno;
- _data->timestamp = state.packet.aps_pts;
-
- if (!state.stream.shdr[state.packet.aps_idx].aps_list)
- state.stream.shdr[state.packet.aps_idx].aps_list = _cdio_list_new ();
-
- _cdio_list_append (state.stream.shdr[state.packet.aps_idx].aps_list, _data);
- }
- break;
-
- default:
- vcd_assert_not_reached ();
- break;
- }
-
- pos += pkt_len;
- pno++;
-
- if (pkt_len != read_len)
- {
- padbytes += (2324 - pkt_len);
-
- if (!padpackets)
- vcd_warn ("mpeg stream will be padded on the fly -- hope that's ok for you!");
-
- padpackets++;
-
- vcd_data_source_seek (obj->data_source, pos);
- }
- }
-
- vcd_data_source_close (obj->data_source);
-
- if (callback)
- {
- _progress.current_pos = pos;
- _progress.current_pack = pno;
- callback (&_progress, user_data);
- }
-
- vcd_assert (pos == length);
-
- obj->info = state.stream;
- obj->scanned = true;
-
- obj->info.playing_time = obj->info.max_pts - obj->info.min_pts;
-
- if (obj->info.min_pts)
- vcd_debug ("pts start offset %f (max pts = %f)",
- obj->info.min_pts, obj->info.max_pts);
-
- vcd_debug ("playing time %f", obj->info.playing_time);
-
- if (!state.stream.scan_data && state.stream.version == MPEG_VERS_MPEG2)
- vcd_warn ("mpeg stream contained no scan information (user) data");
-
- {
- int i;
-
- for (i = 0; i < 3; i++)
- if (obj->info.shdr[i].aps_list)
- _CDIO_LIST_FOREACH (n, obj->info.shdr[i].aps_list)
- {
- struct aps_data *_data = _cdio_list_node_data (n);
-
- _data->timestamp -= obj->info.min_pts;
- }
- }
-
- if (padpackets)
- vcd_warn ("autopadding requires to insert additional %d zero bytes"
- " into MPEG stream (due to %d unaligned packets of %d total)",
- padbytes, padpackets, state.stream.packets);
-
- obj->info.version = state.stream.version;
-}
-
-static double
-_approx_pts (CdioList *aps_list, uint32_t packet_no)
-{
- double retval = 0;
- CdioListNode *node;
-
- struct aps_data *_laps = NULL;
-
- double last_pts_ratio = 0;
-
- _CDIO_LIST_FOREACH (node, aps_list)
- {
- struct aps_data *_aps = _cdio_list_node_data (node);
-
- if (_laps)
- {
- long p = _aps->packet_no;
- double t = _aps->timestamp;
-
- p -= _laps->packet_no;
- t -= _laps->timestamp;
-
- last_pts_ratio = t / p;
- }
-
- if (_aps->packet_no >= packet_no)
- break;
-
- _laps = _aps;
- }
-
- retval = packet_no;
- retval -= _laps->packet_no;
- retval *= last_pts_ratio;
- retval += _laps->timestamp;
-
- return retval;
-}
-
-static void
-_set_scan_msf (msf_t *_msf, long lsn)
-{
- if (lsn == -1)
- {
- _msf->m = _msf->s = _msf->f = 0xff;
- return;
- }
-
- cdio_lba_to_msf (lsn, _msf);
- _msf->s |= 0x80;
- _msf->f |= 0x80;
-}
-
-static void
-_fix_scan_info (struct vcd_mpeg_scan_data_t *scan_data_ptr,
- unsigned packet_no, double pts, CdioList *aps_list)
-{
- CdioListNode *node;
- long _next = -1, _prev = -1, _forw = -1, _back = -1;
-
- _CDIO_LIST_FOREACH (node, aps_list)
- {
- struct aps_data *_aps = _cdio_list_node_data (node);
-
- if (_aps->packet_no == packet_no)
- continue;
- else if (_aps->packet_no < packet_no)
- {
- _prev = _aps->packet_no;
-
- if (pts - _aps->timestamp < 10 && _back == -1)
- _back = _aps->packet_no;
- }
- else if (_aps->packet_no > packet_no)
- {
- if (_next == -1)
- _next = _aps->packet_no;
-
- if (_aps->timestamp - pts < 10)
- _forw = _aps->packet_no;
- }
- }
-
- if (_back == -1)
- _back = packet_no;
-
- if (_forw == -1)
- _forw = packet_no;
-
- _set_scan_msf (&scan_data_ptr->prev_ofs, _prev);
- _set_scan_msf (&scan_data_ptr->next_ofs, _next);
- _set_scan_msf (&scan_data_ptr->back_ofs, _back);
- _set_scan_msf (&scan_data_ptr->forw_ofs, _forw);
-}
-
-int
-vcd_mpeg_source_get_packet (VcdMpegSource *obj, unsigned long packet_no,
- void *packet_buf, struct vcd_mpeg_packet_info *flags,
- bool fix_scan_info)
-{
- unsigned length;
- unsigned pos;
- unsigned pno;
- VcdMpegStreamCtx state;
-
- vcd_assert (obj != NULL);
- vcd_assert (obj->scanned);
- vcd_assert (packet_buf != NULL);
-
- if (packet_no >= obj->info.packets)
- {
- vcd_error ("invalid argument");
- return -1;
- }
-
- if (packet_no < obj->_read_pkt_no)
- {
- vcd_warn ("rewinding mpeg stream...");
- obj->_read_pkt_no = 0;
- obj->_read_pkt_pos = 0;
- }
-
- memset (&state, 0, sizeof (state));
- state.stream.seen_pts = true;
- state.stream.min_pts = obj->info.min_pts;
- state.stream.scan_data_warnings = VCD_MPEG_SCAN_DATA_WARNS + 1;
-
- pos = obj->_read_pkt_pos;
- pno = obj->_read_pkt_no;
- length = vcd_data_source_stat (obj->data_source);
-
- vcd_data_source_seek (obj->data_source, pos);
-
- while (pos < length)
- {
- char buf[2324] = { 0, };
- int read_len = MIN (sizeof (buf), (length - pos));
- int pkt_len;
-
- vcd_data_source_read (obj->data_source, buf, read_len, 1);
-
- pkt_len = vcd_mpeg_parse_packet (buf, read_len,
- fix_scan_info, &state);
-
- vcd_assert (pkt_len > 0);
-
- if (pno == packet_no)
- {
- /* optimized for sequential access,
- thus save pointer to next mpeg pack */
- obj->_read_pkt_pos = pos + pkt_len;
- obj->_read_pkt_no = pno + 1;
-
- if (fix_scan_info
- && state.packet.scan_data_ptr
- && obj->info.version == MPEG_VERS_MPEG2)
- {
- int vid_idx = 0;
- double _pts;
-
- if (state.packet.video[2])
- vid_idx = 2;
- else if (state.packet.video[1])
- vid_idx = 1;
- else
- vid_idx = 0;
-
- if (state.packet.has_pts)
- _pts = state.packet.pts - obj->info.min_pts;
- else
- _pts = _approx_pts (obj->info.shdr[vid_idx].aps_list, packet_no);
-
- _fix_scan_info (state.packet.scan_data_ptr, packet_no,
- _pts, obj->info.shdr[vid_idx].aps_list);
- }
-
- memset (packet_buf, 0, 2324);
- memcpy (packet_buf, buf, pkt_len);
-
- if (flags)
- {
- *flags = state.packet;
- flags->pts -= obj->info.min_pts;
- }
-
- return 0; /* breaking out */
- }
-
- pos += pkt_len;
- pno++;
-
- if (pkt_len != read_len)
- vcd_data_source_seek (obj->data_source, pos);
- }
-
- vcd_assert (pos == length);
-
- vcd_error ("shouldnt be reached...");
-
- return -1;
-}
-
-void
-vcd_mpeg_source_close (VcdMpegSource *obj)
-{
- vcd_assert (obj != NULL);
-
- vcd_data_source_close (obj->data_source);
-}
-
-
-/*
- * Local variables:
- * c-file-style: "gnu"
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- */