Statistics
| Branch: | Revision:

streamers / output.c @ 0bee8166

History | View | Annotate | Download (3.34 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

    
15
#include "measures.h"
16
#include "out-stream.h"
17
#include "dbg.h"
18

    
19
static int next_chunk = -1;
20
static int buff_size;
21

    
22
struct outbuf {
23
  void *data;
24
  int size;
25
  int id;
26
};
27
static struct outbuf *buff;
28

    
29
void output_init(int bufsize)
30
{
31
  if (!buff) {
32
    int i;
33

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

    
49
void buffer_print()
50
{
51
#ifdef DEBUG
52
  int i;
53

    
54
  if (next_chunk < 0) {
55
    return;
56
  }
57

    
58
  dprintf("\toutbuf: %d-> ",next_chunk);
59
  for (i = next_chunk; i < next_chunk + buff_size; i++) {
60
    if (buff[i % buff_size].data) {
61
      dprintf("%d",i % 10);
62
    } else {
63
      dprintf(".");
64
    }
65
  }
66
  dprintf("\n");
67
#endif
68
}
69

    
70
void buffer_free(int i)
71
{
72
  dprintf("\t\tFlush Buf %d: %s\n", i, buff[i].data);
73
  chunk_write(buff[i].id, buff[i].data, buff[i].size);
74
  free(buff[i].data);
75
  buff[i].data = NULL;
76
  dprintf("Next Chunk: %d -> %d\n", next_chunk, buff[i].id + 1);
77
  reg_chunk_playout(true);
78
  next_chunk = buff[i].id + 1;
79
}
80

    
81
void buffer_flush(int id)
82
{
83
  int i = id % buff_size;
84

    
85
  while(buff[i].data) {
86
    buffer_free(i);
87
    i = (i + 1) % buff_size;
88
    if (i == id % buff_size) {
89
      break;
90
    }
91
  }
92
}
93

    
94
void output_deliver(const struct chunk *c)
95
{
96
  if (!buff) {
97
    fprintf(stderr, "Warning: code should use output_init!!! Setting output buffer to 8\n");
98
    output_init(8);
99
  }
100

    
101
  dprintf("Chunk %d delivered\n", c->id);
102
  buffer_print();
103
  if (c->id < next_chunk) {
104
    return;
105
  }
106

    
107
  if (c->id >= next_chunk + buff_size) {
108
    int i;
109

    
110
    /* Initialize buffer with first chunk */
111
    if (next_chunk == -1) {
112
      next_chunk = c->id - buff_size + 1;
113
    }
114

    
115
    /* We might need some space for storing this chunk,
116
     * or the stored chunks are too old
117
     */
118
    for (i = next_chunk; i <= c->id - buff_size; i++) {
119
      if (buff[i % buff_size].data) {
120
        buffer_free(i % buff_size);
121
      } else {
122
        reg_chunk_playout(false);
123
        next_chunk++;
124
      }
125
    }
126
    buffer_flush(next_chunk);
127
    dprintf("Next is now %d, chunk is %d\n", next_chunk, c->id);
128
  }
129

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