Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 74ff12bb

History | View | Annotate | Download (8.84 KB)

1
/*
2
 *  Copyright (c) 2009 Luca Abeni
3
 *
4
 *  This is free software; see gpl-3.0.txt
5
 */
6

    
7
#include <libavformat/avformat.h>
8
#include <stdbool.h>
9

    
10
#include "../input-stream.h"
11
#include "../input.h"                //TODO: for flags. Check if we can do something smarter
12
#define STATIC_BUFF_SIZE 1000 * 1024
13
#define HEADER_REFRESH_PERIOD 50
14

    
15
struct input_stream {
16
  AVFormatContext *s;
17
  bool loop;        //loop on input file infinitely
18
  int audio_stream;
19
  int video_stream;
20
  int64_t last_ts;
21
  int64_t base_ts;
22
  int frames_since_global_headers;
23
};
24

    
25
struct input_stream *input_stream_open(const char *fname, int *period, uint16_t flags)
26
{
27
  struct input_stream *desc;
28
  int i, res;
29

    
30
  avcodec_register_all();
31
  av_register_all();
32

    
33
  desc = malloc(sizeof(struct input_stream));
34
  if (desc == NULL) {
35
    return NULL;
36
  }
37
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
38
  if (res < 0) {
39
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
40

    
41
    return NULL;
42
  }
43

    
44
  res = av_find_stream_info(desc->s);
45
  if (res < 0) {
46
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
47

    
48
    return NULL;
49
  }
50
  desc->video_stream = -1;
51
  desc->audio_stream = -1;
52
  desc->last_ts = 0;
53
  desc->base_ts = 0;
54
  desc->frames_since_global_headers = 0;
55
  desc->loop = flags & INPUT_LOOP;
56
  for (i = 0; i < desc->s->nb_streams; i++) {
57
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
58
      desc->video_stream = i;
59
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
60
              desc->s->streams[i]->r_frame_rate.num,
61
              desc->s->streams[i]->r_frame_rate.den,
62
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
63
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
64
    }
65
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
66
      desc->audio_stream = i;
67
    }
68
  }
69

    
70
  dump_format(desc->s, 0, fname, 0);
71

    
72
  return desc;
73
}
74

    
75
void input_stream_close(struct input_stream *s)
76
{
77
    av_close_input_file(s->s);
78
    free(s);
79
}
80

    
81
int input_stream_rewind(struct input_stream *s)
82
{
83
    int ret;
84

    
85
    ret = av_seek_frame(s->s,-1,0,0);
86
    s->base_ts = s->last_ts;
87

    
88
    return ret;
89
}
90

    
91

    
92
#if 0
93
int input_get_1(struct input_stream *s, struct chunk *c)
94
{
95
    static AVPacket pkt;
96
    static int inited;
97
    AVStream *st;
98
    int res;
99
    static uint8_t static_buff[STATIC_BUFF_SIZE];
100
    static int cid;
101
    uint8_t *p;
102

103
    p = static_buff;
104
    if (inited == 0) {
105
        inited = 1;
106
        res = av_read_frame(s->s, &pkt);
107
        if (res < 0) {
108
            fprintf(stderr, "First read failed: %d!!!\n", res);
109

110
            return 0;
111
        }
112
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
113
            fprintf(stderr, "First frame is not key frame!!!\n");
114

115
            return 0;
116
        }
117
    }
118
    c->timestamp = pkt.dts;
119
    memcpy(p, pkt.data, pkt.size);
120
    p += pkt.size;
121
    while (1) {
122
        res = av_read_frame(s->s, &pkt);
123
        if (res >= 0) {
124
            st = s->s->streams[pkt.stream_index];
125
            if (pkt.flags & PKT_FLAG_KEY) {
126
                c->size = p - static_buff;
127
                c->data = malloc(c->size);
128
                if (c->data == NULL) {
129
                  return 0;
130
                }
131
                memcpy(c->data, static_buff, c->size);
132
                c->attributes_size = 0;
133
                c->attributes = NULL;
134
                c->id = cid++; 
135
                return 1;
136
            }
137
            memcpy(p, pkt.data, pkt.size);
138
            p += pkt.size;
139
        } else {
140
            if (p - static_buff > 0) {
141
                c->size = p - static_buff;
142
                c->data = malloc(c->size);
143
                if (c->data == NULL) {
144
                  return 0;
145
                }
146
                memcpy(c->data, static_buff, c->size);
147
                c->attributes_size = 0;
148
                c->attributes = NULL;
149
                c->id = cid++; 
150
                return 1;
151
            }
152
            return 0;
153
        }
154
    }
155

156
    return 0;
157
}
158
#endif
159

    
160
uint8_t *chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
161
{
162
    AVPacket pkt;
163
    int res;
164
    uint8_t *data;
165
    int header_out, header_size;
166

    
167
    res = av_read_frame(s->s, &pkt);
168
    if (res < 0) {
169
      if (s->loop) {
170
        if (input_stream_rewind(s) >= 0) {
171
          *size = 0;
172
          *ts = s->last_ts;
173

    
174
          return NULL;
175
        }
176
      }
177
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
178
      *size = -1;
179

    
180
      return NULL;
181
    }
182
    if (pkt.stream_index != s->video_stream) {
183
      *size = 0;
184
      *ts = s->last_ts;
185
      av_free_packet(&pkt);
186

    
187
      return NULL;
188
    }
189

    
190
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
191
      header_size = 1 + 2 + 2 + 2 + 2 + 1; // 1 Frame type + 2 width + 2 height + 2 frame rate num + 2 frame rate den + 1 number of frames
192
    }
193
    header_out = (pkt.flags & PKT_FLAG_KEY) != 0;
194
    if (header_out == 0) {
195
      s->frames_since_global_headers++;
196
      if (s->frames_since_global_headers == HEADER_REFRESH_PERIOD) {
197
        s->frames_since_global_headers = 0;
198
        header_out = 1;
199
      }
200
    }
201
    *size = pkt.size + s->s->streams[pkt.stream_index]->codec->extradata_size * header_out + header_size + 2;
202
    data = malloc(*size);
203
    if (data == NULL) {
204
      *size = -1;
205
      av_free_packet(&pkt);
206

    
207
      return NULL;
208
    }
209
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
210
      int num, den;
211

    
212
      data[0] = 1;
213
      data[1] = s->s->streams[pkt.stream_index]->codec->width >> 8;
214
      data[2] = s->s->streams[pkt.stream_index]->codec->width & 0xFF;
215
      data[3] = s->s->streams[pkt.stream_index]->codec->height >> 8;
216
      data[4] = s->s->streams[pkt.stream_index]->codec->height & 0xFF;
217
      num = s->s->streams[pkt.stream_index]->avg_frame_rate.num;
218
      den = s->s->streams[pkt.stream_index]->avg_frame_rate.den;
219
//fprintf(stderr, "Rate: %d/%d\n", num, den);
220
      if (num == 0) {
221
        num = s->s->streams[pkt.stream_index]->r_frame_rate.num;
222
        den = s->s->streams[pkt.stream_index]->r_frame_rate.den;
223
      }
224
      if (num > (1 << 16)) {
225
        num /= 1000;
226
        den /= 1000;
227
      }
228
      data[5] = num >> 8;
229
      data[6] = num & 0xFF;
230
      data[7] = den >> 8;
231
      data[8] = den & 0xFF;
232
      data[9] = 1;
233
      data[10] = (*size - header_size - 2) >> 8;
234
      data[11] = (*size - header_size - 2) & 0xFF;
235
    }
236
    if (header_out && s->s->streams[pkt.stream_index]->codec->extradata_size) {
237
      memcpy(data + header_size + 2, s->s->streams[pkt.stream_index]->codec->extradata, s->s->streams[pkt.stream_index]->codec->extradata_size);
238
      memcpy(data + header_size + 2 + s->s->streams[pkt.stream_index]->codec->extradata_size, pkt.data, pkt.size);
239
    } else {
240
      memcpy(data + header_size + 2, pkt.data, pkt.size);
241
    }
242
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
243
    *ts += s->base_ts;
244
    s->last_ts = *ts;
245
    av_free_packet(&pkt);
246

    
247
    return data;
248
}
249

    
250
#if 0
251
int chunk_read_avs1(void *s_h, struct chunk *c)
252
{
253
    AVFormatContext *s = s_h;
254
    static AVPacket pkt;
255
    static int inited;
256
    AVStream *st;
257
    int res;
258
    int cnt;
259
    static uint8_t static_buff[STATIC_BUFF_SIZE];
260
    uint8_t *p, *pcurr;
261
    static uint8_t *p1;
262
    static struct chunk c2;
263
    int f1;
264
    static int f2;
265

266
    if (p1) {
267
        c2.id = c->id;
268
        *c = c2;
269
        p1 = NULL;
270

271
        return f2;
272
    }
273

274
    p = static_buff;
275
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
276
    if (inited == 0) {
277
        inited = 1;
278
        res = av_read_frame(s, &pkt);
279
        if (res < 0) {
280
            fprintf(stderr, "First read failed: %d!!!\n", res);
281

282
            return 0;
283
        }
284
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
285
            fprintf(stderr, "First frame is not key frame!!!\n");
286

287
            return 0;
288
        }
289
    }
290
    cnt = 0; f1 = 0; f2 = 0;
291
    c->stride_size = 2;
292
    c2.stride_size = 2;
293
    pcurr = p1;
294
    if (pkt.size > 0) {
295
        memcpy(p, pkt.data, pkt.size);
296
        c->frame[0] = p;
297
        c->frame_len[0] = pkt.size;
298
        f1++;
299
        p += pkt.size;
300
    }
301
    while (1) {
302
        res = av_read_frame(s, &pkt);
303
        if (res >= 0) {
304
            st = s->streams[pkt.stream_index];
305
            if (pkt.flags & PKT_FLAG_KEY) {
306
                cnt++;
307
                if (cnt == 2) {
308
                    return f1;
309
                }
310
            }
311
            memcpy(pcurr, pkt.data, pkt.size);
312
            if (pcurr == p) {
313
                c->frame[f1] = pcurr;
314
                c->frame_len[f1] = pkt.size;
315
                p += pkt.size;
316
                pcurr = p1;
317
                f1++;
318
            } else {
319
                c2.frame[f2] = pcurr;
320
                c2.frame_len[f2] = pkt.size;
321
                p1 += pkt.size;
322
                pcurr = p;
323
                f2++;
324
            }
325
        } else {
326
            pkt.size = 0;
327

328
            return f1;
329
        }
330
    }
331

332
    return 0;
333
}
334
#endif