You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
8.6 KiB

/*
* demux_pass.c
*
* Copyright (C) Thomas Oestreich - May 2002
*
* This file is part of transcode, a video stream processing tool
*
* transcode 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, or (at your option)
* any later version.
*
* transcode 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "transcode.h"
#include "libtc/libtc.h"
#include "tcinfo.h"
#include "ioaux.h"
#include "aux_pes.h"
#include "seqinfo.h"
#include "demuxer.h"
#include "packets.h"
int gop, gop_pts, gop_cnt;
/* if you listen carefully, then you can hear the desesperate
* whisper of this code calling for a rewrite. Or for a redesign.
* Or both. -- FR
*/
/* ------------------------------------------------------------
*
* demuxer pass_through mode
*
* ------------------------------------------------------------*/
void tcdemux_pass_through(info_t *ipipe, int *pass, int npass)
{
int bytes, p, id = 0;
int j = 0; // skipped packets counter
char *buffer = NULL;
int payload_id = 0, select = PACKAGE_ALL;
int unit, unit_seek = 0, track = 0, is_track = 0;
int resync_seq1 = 0;
int resync_seq2 = INT_MAX;
int seq_dump = 0;
int seq_seek = 0;
int keep_seq = 0;
int has_pts_dts = 0;
int flag_flush = 0;
// will be switched on as soon start of sequences to flush is reached
int flag_eos = 0;
int flag_notify = 1;
int flag_skip = 0;
int flag_sync_reset = 0;
int flag_sync_active = 0;
const char *logfile;
unsigned int pkt_size = VOB_PACKET_SIZE;
double fps;
// allocate space
buffer = tc_zalloc(pkt_size);
if (!buffer) {
tc_log_perror(__FILE__, "out of memory");
exit(1);
}
// copy info parameter to local variables
verbose = ipipe->verbose;
unit_seek = ipipe->ps_unit;
resync_seq1 = ipipe->ps_seq1;
resync_seq2 = ipipe->ps_seq2;
track = ipipe->track;
select = ipipe->select;
fps = ipipe->fps;
logfile = ipipe->name;
keep_seq = ipipe->keep_seq;
if (keep_seq)
flag_sync_active=1;
unit = unit_seek;
seq_seek = resync_seq1;
seq_dump = resync_seq2 - resync_seq1;
++unit_seek;
++seq_seek;
for (p = 0; p < npass; p++)
tc_log_msg(__FILE__, "pass[%i]=0x%x", p, pass[p]);
for (;;) {
/* ------------------------------------------------------------
*
* (I) read a 2048k block
*
* ------------------------------------------------------------*/
bytes = tc_pread(ipipe->fd_in, buffer, pkt_size);
if (bytes != pkt_size) {
// program end code?
if (bytes == 4) {
if (scan_pack_header(buffer, MPEG_PROGRAM_END_CODE)) {
if (verbose & TC_DEBUG)
tc_log_msg(__FILE__,
"(pid=%i) program stream end code found",
getpid());
break;
}
}
if (bytes)
tc_log_warn(__FILE__,
"invalid program stream packet size (%i/%i)",
bytes, pkt_size);
break;
}
/* ------------------------------------------------------------
*
* (II) packet header ok?
*
* ------------------------------------------------------------*/
if (!scan_pack_header(buffer, TC_MAGIC_VOB)) {
if (flag_notify && (verbose & TC_DEBUG))
tc_log_warn(__FILE__,
"(pid=%i) invalid packet header detected",
getpid());
// something else?
if (scan_pack_header(buffer, MPEG_VIDEO)
| scan_pack_header(buffer, MPEG_AUDIO)) {
/* CAUTION: bitwise OR */
if (verbose & TC_STATS)
tc_log_msg(__FILE__,
"(pid=%i) MPEG system stream detected",
getpid());
if (scan_pack_header(buffer, MPEG_VIDEO))
payload_id = PACKAGE_VIDEO;
if (scan_pack_header(buffer, MPEG_AUDIO))
payload_id = PACKAGE_AUDIO_MP3;
// no further processing
goto flush_packet; /* UGHly */
} else {
tc_log_warn(__FILE__,
"(pid=%i) '0x%02x%02x%02x%02x' not yet supported",
getpid(), buffer[0] & 0xff, buffer[1] & 0xff,
buffer[2] & 0xff, buffer[3] & 0xff);
break;
}
} else {
//MPEG1?
if ((buffer[4] & 0xf0) == 0x20) {
payload_id = PACKAGE_MPEG1;
flag_flush = 1;
if (verbose & TC_STATS)
tc_log_msg(__FILE__,
"(pid=%i) MPEG-1 video stream detected",
getpid());
// no further processing
goto flush_packet;
}
}
/* ------------------------------------------------------------
*
* (III) analyze packet contents
*
* ------------------------------------------------------------*/
// proceed with a valid package, assume defaults
flag_skip = 0; // do not skip
has_pts_dts = 0; // no pts_dts stamp
payload_id = 0; // payload unknown
flag_sync_reset = 0; // no reset of syncinfo
id = buffer[17] & 0xff; //payload id byte
//MPEG 2?
if ((buffer[4] & 0xc0) == 0x40) {
// do not change any flags
if (verbose & TC_STATS) {
//display info only once
tc_log_msg(__FILE__,
"(pid=%i) MPEG-2 video stream detected",
getpid());
}
} else {
// MPEG1
if ((buffer[4] & 0xf0) == 0x20) {
payload_id = PACKAGE_MPEG1;
if (verbose & TC_STATS) {
// display info only once
tc_log_msg(__FILE__,
"(pid=%i) MPEG-1 video stream detected",
getpid());
}
} else {
payload_id = PACKAGE_PASS;
if (verbose & TC_DEBUG)
tc_log_warn(__FILE__,
"(pid=%i) unknown stream packet id detected",
getpid());
}
//flush all MPEG1 stuff
goto flush_packet;
}
/* ------------------------------------------------------------
*
* (IV) audio payload
*
* ------------------------------------------------------------*/
// check payload id
// process this audio packet?
// sync to AC3 audio mode?
if (id == P_ID_AC3)
payload_id = PACKAGE_PRIVATE_STREAM;
// check for subid here:
is_track = id;
if (payload_id == PACKAGE_PRIVATE_STREAM) {
//position of track code
uint8_t *_buf=buffer + 14;
uint8_t *_tmp=_buf + 9 + _buf[8];
is_track = (*_tmp);
}
/* ------------------------------------------------------------
*
* (VII) evaluate scan results - flush packet
*
* ------------------------------------------------------------*/
flush_packet:
for (p = 0; p < npass; p++) {
if (is_track == pass[p]) {
if (tc_pwrite(ipipe->fd_out, buffer, pkt_size) != pkt_size) {
tc_log_perror(__FILE__, "write program stream packet");
exit(1);
}
break;
}
}
// aborting?
if (flag_eos)
break;
//total packs (2k each) counter
++j;
} // process next packet/block
if (buffer != NULL)
tc_free(buffer);
return;
}