File:  [DVB] / multiplexer / splice.c
Revision 1.3: download - view: text, annotated - select for diffs
Mon Apr 30 15:58:29 2001 UTC (23 years, 1 month ago) by oskar
Branches: MAIN
CVS tags: HEAD
Introduce internal data propagation type, with sd_unparsedsi apart from
sd_data and sd_map.
clean up data processing in splicets.c to have clear, short functions.

/*
 * 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"

/* 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",EINP,14,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.
 * Precondition: s!=NULL, p!=NULL, s is stream in target program p
 */
void remove_streamprog (stream_descr *s,
    prog_descr *p)
{
  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",EINP,15,sid,s0);
      return (s0);
    }
    s0 = s;
    s += 1;
  }
  warn (LIMP,"Found SID",EINP,15,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",EINP,13,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",EINP,13,1,p->stream[i]->sourceid);
          return (p->stream[i]);
        }
        pmt = pmt->next;
      }
    }
  }
  return (NULL);
}


LinuxTV legacy CVS <linuxtv.org/cvs>