Statistics
| Branch: | Revision:

streamers / output-grapes.c @ 327fc1a6

History | View | Annotate | Download (3.96 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *  Copyright (c) 2010 Csaba Kiraly
4
 *
5
 *  This is free software; see gpl-3.0.txt
6
 */
7
#include <unistd.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include <stdint.h>
11
#include <stdio.h>
12

    
13
#include <chunk.h>
14
#include <chunkiser.h>
15

    
16
#include "output.h"
17
#include "measures.h"
18
#include "dbg.h"
19

    
20
static int next_chunk = -1;
21
static int buff_size;
22
extern bool chunk_log;
23

    
24
struct outbuf {
25
  struct chunk c;
26
};
27
static struct outbuf *buff;
28
static struct output_stream *out;
29

    
30
void output_init(int bufsize, const char *config)
31
{
32
  out = out_stream_init(config, "media=av");
33
  if (out == NULL) {
34
     fprintf(stderr, "Error: can't initialize output module\n");
35
     exit(1);
36
  }
37
  if (!buff) {
38
    int i;
39

    
40
    buff_size = bufsize;
41
    buff = malloc(sizeof(struct outbuf) * buff_size);
42
    if (!buff) {
43
     fprintf(stderr, "Error: can't allocate output buffer\n");
44
     exit(1);
45
    }
46
    for (i = 0; i < buff_size; i++) {
47
      buff[i].c.data = NULL;
48
    }
49
  } else {
50
   fprintf(stderr, "Error: output buffer re-init not allowed!\n");
51
   exit(1);
52
  }
53
}
54

    
55
static void buffer_print(void)
56
{
57
#ifdef DEBUG
58
  int i;
59

    
60
  if (next_chunk < 0) {
61
    return;
62
  }
63

    
64
  dprintf("\toutbuf: %d-> ",next_chunk);
65
  for (i = next_chunk; i < next_chunk + buff_size; i++) {
66
    if (buff[i % buff_size].c.data) {
67
      dprintf("%d",i % 10);
68
    } else {
69
      dprintf(".");
70
    }
71
  }
72
  dprintf("\n");
73
#endif
74
}
75

    
76
static void buffer_free(int i)
77
{
78
  dprintf("\t\tFlush Buf %d: %s\n", i, buff[i].c.data);
79
  chunk_write(out, &buff[i].c);
80
  free(buff[i].c.data);
81
  buff[i].c.data = NULL;
82
  dprintf("Next Chunk: %d -> %d\n", next_chunk, buff[i].c.id + 1);
83
  reg_chunk_playout(buff[i].c.id, true, buff[i].c.timestamp);
84
  next_chunk = buff[i].c.id + 1;
85
}
86

    
87
static void buffer_flush(int id)
88
{
89
  int i = id % buff_size;
90

    
91
  while(buff[i].c.data) {
92
    buffer_free(i);
93
    i = (i + 1) % buff_size;
94
    if (i == id % buff_size) {
95
      break;
96
    }
97
  }
98
}
99

    
100
void output_deliver(const struct chunk *c)
101
{
102
  if (!buff) {
103
    fprintf(stderr, "Warning: code should use output_init!!! Setting output buffer to 8\n");
104
    output_init(8, NULL);
105
  }
106

    
107
  dprintf("Chunk %d delivered\n", c->id);
108
  buffer_print();
109
  if (c->id < next_chunk) {
110
    return;
111
  }
112

    
113
  /* Initialize buffer with first chunk */
114
  if (next_chunk == -1) {
115
    next_chunk = c->id; // FIXME: could be anything between c->id and (c->id - buff_size + 1 > 0) ? c->id - buff_size + 1 : 0
116
  }
117

    
118
  if (c->id >= next_chunk + buff_size) {
119
    int i;
120

    
121
    /* We might need some space for storing this chunk,
122
     * or the stored chunks are too old
123
     */
124
    for (i = next_chunk; i <= c->id - buff_size; i++) {
125
      if (buff[i % buff_size].c.data) {
126
        buffer_free(i % buff_size);
127
      } else {
128
        reg_chunk_playout(c->id, false, c->timestamp); // FIXME: some chunks could be counted as lost at the beginning, depending on the initialization of next_chunk
129
        next_chunk++;
130
      }
131
    }
132
    buffer_flush(next_chunk);
133
    dprintf("Next is now %d, chunk is %d\n", next_chunk, c->id);
134
  }
135

    
136
  dprintf("%d == %d?\n", c->id, next_chunk);
137
  if (c->id == next_chunk) {
138
    dprintf("\tOut Chunk[%d] - %d: %s\n", c->id, c->id % buff_size, c->data);
139
    chunk_write(out, c);
140
    reg_chunk_playout(c->id, true, c->timestamp);
141
    next_chunk++;
142
    buffer_flush(next_chunk);
143
  } else {
144
    dprintf("Storing %d (in %d)\n", c->id, c->id % buff_size);
145
    if (buff[c->id % buff_size].c.data) {
146
      if (buff[c->id % buff_size].c.id == c->id) {
147
        /* Duplicate of a stored chunk */
148
        if(chunk_log){fprintf(stderr,"Duplicate! chunkID: %d\n", c->id);}
149
        dprintf("\tDuplicate!\n");
150
        reg_chunk_duplicate();
151
        return;
152
      }
153
      fprintf(stderr, "Crap!, chunkid:%d, storedid: %d\n", c->id, buff[c->id % buff_size].c.id);
154
      exit(-1);
155
    }
156
    /* We previously flushed, so we know that c->id is free */
157
    memcpy(&buff[c->id % buff_size].c, c, sizeof(struct chunk));
158
    buff[c->id % buff_size].c.data = malloc(c->size);
159
    memcpy(buff[c->id % buff_size].c.data, c->data, c->size);
160
  }
161
}