Changes to allow tsserve to serve all the original TS data to

a client, rather than just the PES for video/audio.

--HG--
extra : convert_revision : svn%3Aeff31bef-be4a-0410-a8fe-e47997df2690/trunk%4017
issue20
tibs 2008-06-25 21:24:17 +00:00
rodzic 18acac0c76
commit 7a02df44f7
4 zmienionych plików z 145 dodań i 36 usunięć

87
pes.c
Wyświetl plik

@ -38,6 +38,7 @@
#include "pes_fns.h"
#include "pidint_fns.h"
#include "h262_fns.h"
#include "tswrite_fns.h"
#include "misc_fns.h"
//#define DEBUG
@ -1366,6 +1367,7 @@ static int read_next_PES_packet_from_TS(PES_reader_p reader,
for (;;)
{
int err;
byte *ts_packet;
int payload_unit_start_indicator;
byte *adapt;
int adapt_len;
@ -1377,14 +1379,21 @@ static int read_next_PES_packet_from_TS(PES_reader_p reader,
// Remember the position of the packet we're going to read
reader->posn = reader->tsreader->posn;
// Read the next packet
err = get_next_TS_packet(reader->tsreader,&pid,
&payload_unit_start_indicator,
&adapt,&adapt_len,&payload,&payload_len);
// And read it
// Remember that `ts_packet` will not persist, as it is a pointer
// into the TS buffering innards
err = read_next_TS_packet(reader->tsreader,&ts_packet);
if (err == EOF)
{
// Check for an unbounded (length indicated as zero) video stream
// with a PES packet outstanding
// If we've been given EOF, then either we're just *read* EOF
// instead of a packet (the obvious case), or we read some data
// that was terminated by EOF last time, and the EOF was "deferred"
// by the underlying buffering methods.
// So, just in case, we'll check for an unbounded (length marked as
// zero) video stream PES packet
// XXX Note that an unbounded packet will thus not be correctly written
// XXX out when we've been asked to write_TS_packets -- fix this if it
// XXX ever becomes a problem
check_for_EOF_packet(reader,packet_data);
if (*packet_data == NULL)
return EOF;
@ -1397,6 +1406,29 @@ static int read_next_PES_packet_from_TS(PES_reader_p reader,
reader->posn);
return 1;
}
err = split_TS_packet(ts_packet,&pid,&payload_unit_start_indicator,
&adapt,&adapt_len,&payload,&payload_len);
if (err)
{
fprintf(stderr,"### Error interpreting TS packet at " OFFSET_T_FORMAT "\n",
reader->posn);
return 1;
}
// If we're writing out TS packets directly to a client, then this
// is probably a sensible place to do it.
if (reader->write_TS_packets && reader->tswriter != NULL &&
!reader->suppress_writing)
{
err = tswrite_write(reader->tswriter,ts_packet,pid,FALSE,0);
if (err)
{
fprintf(stderr,"### Error writing TS packet (PID %04x) at "
OFFSET_T_FORMAT "\n",pid,reader->posn);
return 1;
}
}
#if DEBUG_PES_ASSEMBLY
printf("@@@ TS packet at " OFFSET_T_FORMAT " with pid %3x",
@ -1467,7 +1499,7 @@ static int read_next_PES_packet_from_TS(PES_reader_p reader,
free(reader->pmt_data);
reader->pmt_data = NULL; reader->pmt_data_len = reader->pmt_data_used = 0;
if (reader->write_PES_packets)
if (reader->write_PES_packets && !reader->suppress_writing)
{
// XXX We *probably* should check if it's changed before doing this,
// but at least by outputting it again we ensure it's current
@ -1688,6 +1720,8 @@ static int build_PES_reader_datastructure(int give_info,
new->tswriter = NULL;
new->write_PES_packets = FALSE;
new->write_TS_packets = FALSE;
new->suppress_writing = TRUE;
new->dont_write_current_packet = FALSE;
new->pes_padding = 0;
@ -2293,6 +2327,7 @@ extern int read_next_PES_packet(PES_reader_p reader)
if (reader->packet != NULL)
{
if (reader->write_PES_packets && reader->tswriter != NULL &&
!reader->suppress_writing &&
!reader->dont_write_current_packet)
{
// Aha - we need to output the previous PES packet
@ -3579,34 +3614,42 @@ extern int find_ESCR_in_PES(byte data[],
// Server support
// ============================================================
/*
* Prepare for PES packets being written out to a TS writer, and
* request that they be written out.
* Packets can be written out to a client via a TS writer, as a
* "side effect" of reading them. The original mechanism was to
* write out PES packets (as TS) as they are read. This will work
* for PS or TS data, and writes out only those PES packets that
* have been read for video or audio data.
*
* The effect is that, each time a new PES packet is read in, it will
* be written out to the TS output stream.
* An alternative, which will only work for TS input data, is
* to write out TS packets as they are read. This will write all
* TS packets to the client.
*
* - `reader` is our PES reader context
* - `tswriter` is the TS writer
* - if `write_PES`, then write PES packets out as they are read from
* the input, otherwise write TS packets.
* - `program_freq` is how often to write out program data (PAT/PMT)
* if we are writing PES data (if we are writing TS data, then the
* program data will be in the original TS packets)
*/
extern void set_server_output(PES_reader_p reader,
TS_writer_p tswriter,
int write_PES,
int program_freq)
{
reader->tswriter = tswriter;
reader->program_freq = program_freq;
reader->program_index = 0;
reader->write_PES_packets = TRUE;
reader->write_PES_packets = write_PES;
reader->write_TS_packets = !write_PES;
reader->suppress_writing = FALSE;
return;
}
/*
* Start PES packets being written out to a TS writer (again).
* Start packets being written out to a TS writer (again).
*
* The effect is that, each time a new PES packet is read in, it will
* be written out to the TS output stream.
*
* If PES packets were already being written out, this does nothing.
* If packets were already being written out, this does nothing.
*
* If set_server_output() has not been called to define a TS writer
* context, this will have no effect.
@ -3616,21 +3659,21 @@ extern void set_server_output(PES_reader_p reader,
extern void start_server_output(PES_reader_p reader)
{
if (reader != NULL)
reader->write_PES_packets = TRUE;
reader->suppress_writing = FALSE;
return;
}
/*
* Stop PES packets being written out to a TS writer.
* Stop packets being written out to a TS writer.
*
* If PES packets were already not being written out, this does nothing.
* If packets were already not being written out, this does nothing.
*
* If `reader` is NULL, nothing is done.
*/
extern void stop_server_output(PES_reader_p reader)
{
if (reader != NULL)
reader->write_PES_packets = FALSE;
reader->suppress_writing = TRUE;
return;
}
@ -3644,6 +3687,8 @@ extern void stop_server_output(PES_reader_p reader)
* the recipient, as the extra data (which has an irrelevant stream id)
* will be ignored by the video processor, but not by preceding systems.
*
* This does nothing if TS packets are being output directly.
*
* - `reader` is our PES reader context
* - `extra` is how many extra packets to output per "real" packet.
*/

Wyświetl plik

@ -200,6 +200,17 @@ struct PES_reader
// with an irrelevant stream id).
int pes_padding;
// If the original data is TS, and we want to send *all* of said data
// to the server, it is sensible to write the *TS packets* as a side
// effect of reading, rather than the PES packets. Thus we also have
int write_TS_packets;
// Obviously, one assumes that we are not going to be doing both at
// the same time (since they write through the same tswriter interface)
// In either case, sometimes it is useful to suppress writing packets
// out for a while
int suppress_writing;
// Debugging: if this is set, and the appropriate code is compiled into
// pes.c (see DEBUG_READ_PACKETS), then report on each PES packet read
// and written. Even if DEBUG_READ_PACKETS is not defined, some output

Wyświetl plik

@ -472,34 +472,43 @@ extern void report_PES_data_array2(int stream_type,
// Server support
// ============================================================
/*
* Prepare for PES packets being written out to a TS writer, and
* request that they be written out.
* Packets can be written out to a client via a TS writer, as a
* "side effect" of reading them. The original mechanism was to
* write out PES packets (as TS) as they are read. This will work
* for PS or TS data, and writes out only those PES packets that
* have been read for video or audio data.
*
* The effect is that, each time a new PES packet is read in, it will
* be written out to the TS output stream.
* An alternative, which will only work for TS input data, is
* to write out TS packets as they are read. This will write all
* TS packets to the client.
*
* - `reader` is our PES reader context
* - `tswriter` is the TS writer
* - if `write_PES`, then write PES packets out as they are read from
* the input, otherwise write TS packets.
* - `program_freq` is how often to write out program data (PAT/PMT)
* if we are writing PES data (if we are writing TS data, then the
* program data will be in the original TS packets)
*/
extern void set_server_output(PES_reader_p reader,
TS_writer_p tswriter,
int write_PES,
int program_freq);
/*
* Start PES packets being written out to a TS writer (again).
* Start packets being written out to a TS writer (again).
*
* The effect is that, each time a new PES packet is read in, it will
* be written out to the TS output stream.
* If packets were already being written out, this does nothing.
*
* If PES packets were already being written out, this does nothing.
* If set_server_output() has not been called to define a TS writer
* context, this will have no effect.
*
* If `reader` is NULL, nothing is done.
*/
extern void start_server_output(PES_reader_p reader);
/*
* Stop PES packets being written out to a TS writer.
* Stop packets being written out to a TS writer.
*
* If PES packets were already not being written out, this does nothing.
* If packets were already not being written out, this does nothing.
*
* If set_server_output() has not been called to define a TS writer
* context, this will have no effect.
@ -517,6 +526,8 @@ extern void stop_server_output(PES_reader_p reader);
* the recipient, as the extra data (which has an irrelevant stream id)
* will be ignored by the video processor, but not by preceding systems.
*
* This does nothing if TS packets are being output directly.
*
* - `reader` is our PES reader context
* - `extra` is how many extra packets to output per "real" packet.
*/

Wyświetl plik

@ -123,6 +123,9 @@ struct tsserve_context
int dolby_is_dvb;
int force_stream_type;
int repeat_program_every;
// Transport Stream specific options
int tsdirect;
};
typedef struct tsserve_context *tsserve_context_p;
@ -2057,7 +2060,8 @@ static int play_pes_packets(PES_reader_p reader[MAX_INPUT_FILES],
// Request that PES packets be written out to the TS writer as
// a "side effect" of reading them in
set_server_output(reader[ii],tswriter,context->repeat_program_every);
set_server_output(reader[ii],tswriter,!context->tsdirect,
context->repeat_program_every);
set_server_padding(reader[ii],context->pes_padding);
}
@ -2115,6 +2119,18 @@ static int test_play(PES_reader_p reader,
int started = FALSE;
int ii;
if (num_fast == 0 && num_faster == 0 && num_reverse == 0)
{
// Special case -- just play through
printf(">> Just playing at normal speed\n");
set_PES_reader_video_only(reader,video_only);
err = play_normal(stream,tswriter,verbose,quiet,0,reverse_data);
if (err == EOF)
return 0;
else
return err;
}
printf(">> Going through sequence twice\n");
for (ii=0; ii<2; ii++)
@ -3080,7 +3096,8 @@ static int test_reader(tsserve_context_p context,
// Actually read the input and write the output...
// Request that PES packets be written out to the TS writer as
// a "side effect" of reading them in
set_server_output(reader,tswriter,context->repeat_program_every);
set_server_output(reader,tswriter,!context->tsdirect,
context->repeat_program_every);
set_server_padding(reader,context->pes_padding);
// And play...
@ -3191,12 +3208,15 @@ static int command_reader(tsserve_context_p context,
return 1;
}
// Request that PES packets be written out to the TS writer as
// a "side effect" of reading them in
// Request that packets be written out to the TS writer as a "side effect" of
// reading them in. The default is to write PES packets (just for the video
// and audio data), but the alternative is to write all TS packets (if the
// data *is* TS)
for (ii = 0; ii < MAX_INPUT_FILES; ii++)
if (reader[ii] != NULL)
{
set_server_output(reader[ii],tswriter,context->repeat_program_every);
set_server_output(reader[ii],tswriter,!context->tsdirect,
context->repeat_program_every);
set_server_padding(reader[ii],context->pes_padding);
}
@ -3381,6 +3401,18 @@ static void print_detailed_usage()
" -dolby dvb Use stream type 0x06 (the default)\n"
" -dolby atsc Use stream type 0x81\n"
"\n"
"Transport Stream Switches:\n"
"\n"
" The following switches are only applicable if the input data is TS.\n"
"\n"
" -tsdirect In normal play, copy all TS packets to the client,\n"
" instead of just sending the PES packets for the video\n"
" and audio streams'\n"
"\n"
" Note that when -tsdirect is specified, PES packets are still inspected\n"
" to allow building up the fast forward/reverse indices.\n"
" Also, -prepeat, -pes_padding and -drop will have no effect with this switch.\n"
"\n"
"Other stuff:\n"
"\n"
" -prepeat <n> Output the program data (PAT/PMT) after every <n>\n"
@ -3452,6 +3484,9 @@ static void print_detailed_usage()
" -r <nr> speed, then <nn> at normal speed again, then\n"
" reverse past <nr>. Repeat until stopped.\n"
"\n"
" If '-f 0 -ff 0 -r 0' is specified, then the data will just play at\n"
" normal speed, ignoring -n.\n"
"\n"
" -skiptest Test forwards and backwards skipping.\n"
"\n"
" -output <name>, -o <name>\n"
@ -3506,6 +3541,9 @@ int main(int argc, char **argv)
context.pcr_pid = context.video_pid; // Use PCRs from the video stream
context.repeat_program_every = 100;
// Transport Stream specific options
context.tsdirect = FALSE; // Write to server as a side effect of PES reading
context.force_stream_type = FALSE;
context.want_h262 = TRUE; // shouldn't matter
context.dolby_is_dvb = TRUE;
@ -3546,6 +3584,10 @@ int main(int argc, char **argv)
action = ACTION_TEST;
skiptest = FALSE;
}
else if (!strcmp("-tsdirect",argv[argno]))
{
context.tsdirect = TRUE; // Write to server as a side effect of TS reading
}
else if (!strcmp("-n",argv[argno]))
{
CHECKARG("tsserve",argno);