File:  [DVB] / multiplexer / splice.c
Revision 1.5: download - view: text, annotated - select for diffs
Thu May 3 13:21:45 2001 UTC (23 years, 1 month ago) by oskar
Branches: MAIN
CVS tags: HEAD
Add command '--config' for feed back concerning current target stream configuration.
Do the usual bug fixes.

/*
 * ISO 13818 stream multiplexer
 * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
 * Author: Oskar Schirmer (oskar@convergence.de)
 */

/*
 * Module:  Splice
 * Purpose: Service functions for specific Splice* modules
 *
 * This module provides functions needed for splicing
 * which are independent from the splice type.
 */

#include "global.h"
#include "error.h"
#include "splice.h"
#include "input.h"
#include "pes.h"

t_msec next_psi_periodic;
t_msec psi_frequency_msec;
boolean psi_frequency_changed;

boolean configuration_on;
boolean configuration_changed;
const char *configuration_total = "Conf: progs: %d\n";

boolean splice_init (void)
{
  psi_frequency_msec = 0;
  psi_frequency_changed = FALSE;
  configuration_on = FALSE;
  return (splice_specific_init ());
}

/* Connect a stream with a target program.
 * programnb denotes the program to connect,
 * stream is the stream to connect,
 * all further parameters are as with input_openstream.
 * If stream is NULL, open a stream first.
 * Add the stream to the programs list of streams and vice versa.
 * Precondition: f!=NULL
 * Return: the changed stream on success, the unchanged "stream" otherwise
 */
stream_descr *connect_streamprog (file_descr *f,
    int programnb,
    int sourceid,
    int streamid,
    int streamtype,
    stream_descr *stream,
    stream_descr *mapstream,
    boolean mention)
{
  stream_descr *s;
  prog_descr *p;
  if (stream == NULL) {
    s = input_openstream (f,sourceid,streamid<0?-streamid:streamid,
            streamtype,sd_data,mapstream);
  } else {
    if (streamid < 0) {
      streamid = -streamid;
      warn (LWAR,"Cannot refind sid",ESPC,1,1,streamid);
    }
    s = stream;
  }
  if (s != NULL) {
    p = splice_openprog (programnb);
    if (p != NULL) {
      if (input_addprog (s,p)) {
        if (splice_addstream (p,s,streamid>=0) > 0) {
/*
          if (p->pcr_pid < 0) {
            if (xxx) {
              p->pcr_pid = s->u.d.pid;
              s->u.d.has_clockref = TRUE;
              s->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
            }
          }
*/
          s->endaction = ENDSTR_WAIT;
          s->u.d.mention = mention;
          return (s);
        }
        input_delprog (s,p);
      }
      if (p->streams <= 0) {
        splice_closeprog (p);
      }
    }
    if (stream == NULL) {
      input_closestream (s);
    }
  }
  return (stream);
}

/* Unlink a stream from a target program.
 * If the stream comes out to be in no program then, close it.
 *   This function may be used only, if the program in question will either
 *   be non-empty after the call, or will be closed by the calling function.
 * Precondition: s!=NULL, p!=NULL
 */
void unlink_streamprog (stream_descr *s,
    prog_descr *p)
{
  splice_delstream (p,s);
  input_delprog (s,p);
  if (s->u.d.progs <= 0) {
    file_descr *f;
    f = s->fdescr;
    input_closestream (s);
    input_closefileifunused (f);
  }
}

/* Remove a stream from a target program.
 * Close stream and/or program, if not contained in another program or stream.
 * The input file is no longer automatic, because we do manual changes here.
 * Precondition: s!=NULL, p!=NULL, s is stream in target program p
 */
void remove_streamprog (stream_descr *s,
    prog_descr *p)
{
  s->fdescr->automatic = FALSE;
  if (p->streams > 1) {
    unlink_streamprog (s,p);
  } else {
    splice_closeprog (p);
  }
}

/* Find the right stream in a program
 * Precondition: p!=NULL
 * Return: stream, if found, NULL otherwise
 */
stream_descr *get_streamprog (prog_descr *p,
    int streamid)
{
  int i;
  i = p->streams;
  while (--i >= 0) {
    stream_descr *s;
    s = p->stream[i];
    if (s->stream_id == streamid) {
      return (s);
    }
  }
  return (NULL);
}

/* Find a free stream ID in a program that is equivalent to the given stream id
 * Precondition: p!=NULL
 * Return: Free ID, if found; given sid otherwise.
 */
int splice_findfreestreamid (prog_descr *p,
    int sid)
{
  int s0, s, n;
  s0 = sid;
  if ((sid >= PES_CODE_AUDIO)
   && (sid < (PES_CODE_AUDIO+PES_NUMB_AUDIO))) {
    s = PES_CODE_AUDIO;
    n = PES_NUMB_AUDIO;
  } else if ((sid >= PES_CODE_VIDEO)
   && (sid < (PES_CODE_VIDEO+PES_NUMB_VIDEO))) {
    s = PES_CODE_VIDEO;
    n = PES_NUMB_VIDEO;
  } else {
    s = sid;
    n = 1;
  }
  while (--n >= 0) {
    int i;
    i = p->streams;
    while ((--i >= 0)
        && (p->stream[i]->stream_id != s0)) {
    }
    if (i < 0) {
      warn (LIMP,"Found SID free",ESPC,2,sid,s0);
      return (s0);
    }
    s0 = s;
    s += 1;
  }
  warn (LIMP,"Found SID",ESPC,2,sid,sid);
  return (sid);
}

/* Check if there is a source pcr stream in a target program
 * Precondition: p!=NULL
 * Return: pcr-stream, if found; NULL otherwise.
 */
stream_descr *splice_findpcrstream (prog_descr *p)
{
  int i;
  pmt_descr *pmt;
  warn (LIMP,"Find PCR Stream",ESPC,3,0,p->program_number);
  i = p->streams;
  while (--i >= 0) {
    if (p->stream[i]->fdescr->content == ct_transport) {
      pmt = p->stream[i]->fdescr->u.ts.pat;
      while (pmt != NULL) {
        if (pmt->pcr_pid == p->stream[i]->sourceid) {
          warn (LIMP,"Found PCR Stream",ESPC,3,1,p->stream[i]->sourceid);
          return (p->stream[i]);
        }
        pmt = pmt->next;
      }
    }
  }
  return (NULL);
}

/* Print configuration for one program
 * Precondition: p!=NULL
 */
void splice_one_configuration (prog_descr *p)
{
  int i;
  i = p->streams;
  fprintf (stderr, "Conf: prog:%04X pmt:%04hX pcr:%04hX streams:%2d\n",
      p->program_number, p->pmt_pid, p->pcr_pid, i);
  while (--i >= 0) {
    stream_descr *s;
    s = p->stream[i];
    fprintf (stderr, "Conf: stream:%04hX sid:%02X type:%02X "
      "file:%d source:%04hX num:%2d name:%s\n",
      s->u.d.pid, s->stream_id, s->stream_type,
      s->fdescr->content, s->sourceid, s->fdescr->filerefnum, s->fdescr->name);
  }
}

void splice_set_configuration (boolean on)
{
  configuration_on = on;
  configuration_changed = TRUE;
}


LinuxTV legacy CVS <linuxtv.org/cvs>