Statistics
| Branch: | Revision:

grapes / src / Chunkiser / input-stream-ts.c @ 997c2b68

History | View | Annotate | Download (4.39 KB)

1 f31ebd3b Luca Abeni
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *
4
 *  This is free software; see gpl-3.0.txt
5
 */
6
7
#include <sys/types.h>
8
#include <sys/stat.h>
9
#include <fcntl.h>
10
#include <unistd.h>
11
#include <errno.h>
12
#include <stdint.h>
13
#include <stdlib.h>
14
#include <string.h>
15
#include <stdio.h>
16
17
#include "chunkiser_iface.h"
18
#include "config.h"
19
20
struct chunkiser_ctx {
21
  int loop;        //loop on input file infinitely
22
  int pkts_per_chunk;
23 997c2b68 Luca Abeni
  int size;
24
  int bufsize;
25
  int pcr_period;
26
  uint8_t *buff;
27
  uint64_t old_pcr;
28 f31ebd3b Luca Abeni
  int fds[2];
29
};
30
#define DEFAULT_PKTS 512
31 997c2b68 Luca Abeni
#define BUFSIZE_INCR (512 * 188)
32 f31ebd3b Luca Abeni
33
static void ts_resync(uint8_t *buff, int *size)
34
{
35
  uint8_t *p = buff;
36
37
  fprintf(stderr, "Resynch!\n");
38
  while((p - buff < *size) && (*p != 0x47)) {
39
    p++;
40
  }
41
  if (p - buff < *size) {
42
    memmove(buff, p, *size - (p - buff));
43
    *size -= (p - buff);
44
  } else {
45
    *size = 0;
46
  }
47
}
48
49
static struct chunkiser_ctx *ts_open(const char *fname, int *period, const char *config)
50
{
51
  struct tag *cfg_tags;
52
  struct chunkiser_ctx *res;
53
54
  res = malloc(sizeof(struct chunkiser_ctx));
55
  if (res == NULL) {
56
    return NULL;
57
  }
58
59 997c2b68 Luca Abeni
  res->size = res->bufsize = 0;
60
  res->buff = NULL;
61 f31ebd3b Luca Abeni
  res->loop = 0;
62 997c2b68 Luca Abeni
  res->pcr_period = 100000 / 100 * 9;
63
  res->old_pcr = 0;
64 f31ebd3b Luca Abeni
  res->fds[0] = open(fname, O_RDONLY);
65
  if (res->fds[0] < 0) {
66
    free(res);
67
68
    return NULL;
69
  }
70
  res->fds[1] = -1;
71
72
  res->pkts_per_chunk = DEFAULT_PKTS;
73
  cfg_tags = config_parse(config);
74
  if (cfg_tags) {
75
    const char *access_mode;
76
77
    config_value_int(cfg_tags, "loop", &res->loop);
78
    config_value_int(cfg_tags, "pkts", &res->pkts_per_chunk);
79 997c2b68 Luca Abeni
    config_value_int(cfg_tags, "pcr_period", &res->pcr_period);
80 f31ebd3b Luca Abeni
    access_mode = config_value_str(cfg_tags, "mode");
81
    if (access_mode && !strcmp(access_mode, "nonblock")) {
82
      fcntl(res->fds[0], F_SETFL, O_NONBLOCK);
83
    }
84
  }
85
  free(cfg_tags);
86 997c2b68 Luca Abeni
  if (res->pcr_period) {
87
    *period = res->pcr_period;
88
  } else {
89
    *period = 0;
90
  }
91 f31ebd3b Luca Abeni
92
  return res;
93
}
94
95
static void ts_close(struct chunkiser_ctx *s)
96
{
97
  close(s->fds[0]);
98
  free(s);
99
}
100
101
static uint8_t *ts_chunkise(struct chunkiser_ctx *s, int id, int *size, uint64_t *ts)
102
{
103
  uint8_t *res;
104
105 997c2b68 Luca Abeni
  if (!s->pcr_period) {
106
    res = malloc(s->pkts_per_chunk * 188);
107
    if (res == NULL) {
108
      *size = -1;
109 f31ebd3b Luca Abeni
110 997c2b68 Luca Abeni
      return NULL;
111
    }
112
    *ts = 0;                /* FIXME: Read the PCR!!! */
113
    *size = read(s->fds[0], res, s->pkts_per_chunk * 188);
114
    if (*size && (res[0] != 0x47)) {
115
      int err;
116
117
      ts_resync(res, size);
118
      if (size) {
119
        err = read(s->fds[0], res + *size, s->pkts_per_chunk * 188 - *size);
120
        if (err > 0) {
121
          *size += err;
122
        }
123
      }
124
    }
125
  } else {
126
    int done;
127
128
    res = NULL;
129
    *size = 0;
130
    if (s->size + 188 > s->bufsize) {
131
      s->bufsize += BUFSIZE_INCR;
132
      s->buff = realloc(s->buff, s->bufsize);
133
    }
134
    done = 0;
135
    while(!done) {
136
      uint8_t *p;
137
      int err;
138
139
      p = s->buff + s->size;
140
      err = read(s->fds[0], p, 188);
141
      if (err == 188) {
142
        if (*p != 0x47) {
143
          ts_resync(p, &err);
144
          if (err) {
145
            err += read(s->fds[0], p + err, 188 - err);
146
          }
147
        }
148
        if (err != 188) {
149
          done = 1;
150
        } else {
151
          s->size += 188;
152
          if (p[3] & 0x20) {
153
            fprintf(stderr, "Adaptation field!!! Size: %d\n", p[4]);
154
            if (p[5] & 0x10) {
155
              unsigned long long int pcr;
156
157
              fprintf(stderr, "PCR!!!\n");
158
              pcr = p[6] << 24 | p[7] << 16 | p[8] << 8 | p[9];
159
              pcr = pcr << 1 | p[10] >> 7;
160
              fprintf(stderr, "%llu", pcr);
161
              if (pcr > s->old_pcr + s->pcr_period) {
162
                *ts = pcr / 9 * 100;
163
                *size = s->size;
164
                res = s->buff;
165
                s->old_pcr = pcr;
166
                s->buff = NULL;
167
                s->size = 0;
168
                s->bufsize = 0;
169
                done = 1;
170
              }
171
            }
172
          }
173
        }
174
      } else {
175
        done = 1;
176
      }
177 f31ebd3b Luca Abeni
    }
178
  }
179
  if (*size % 188) {
180
    fprintf(stderr, "WARNING!!! Strange input size!\n");
181
    *size = (*size / 188) * 188;
182
  }
183
  if ((*size == 0) && (errno != EAGAIN)) {
184
    *size = -1;
185
    if (s->loop) {
186
      if (lseek(s->fds[0], 0, SEEK_SET) == 0) {
187
        *size = 0;
188
      }
189
    }
190
    free(res);
191
    res = NULL;
192
  }
193
194
  return res;
195
}
196
197
const int *ts_get_fds(const struct chunkiser_ctx *s)
198
{
199
  return s->fds;
200
}
201
202
struct chunkiser_iface in_ts = {
203
  .open = ts_open,
204
  .close = ts_close,
205
  .chunkise = ts_chunkise,
206
  .get_fds = ts_get_fds,
207
};