Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 421c2dc2

History | View | Annotate | Download (10.4 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 "../dbg.h"
11
#include "../input-stream.h"
12
#include "../payload.h"
13
#include "../input.h"                //TODO: for flags. Check if we can do something smarter
14

    
15
#define STATIC_BUFF_SIZE 1000 * 1024
16
#define HEADER_REFRESH_PERIOD 50
17

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

    
28
static uint8_t codec_type(enum CodecID cid)
29
{
30
  switch (cid) {
31
    case CODEC_ID_MPEG1VIDEO:
32
    case CODEC_ID_MPEG2VIDEO:
33
      return 1;
34
    case CODEC_ID_H261:
35
      return 2;
36
    case CODEC_ID_H263P:
37
    case CODEC_ID_H263:
38
      return 3;
39
    case CODEC_ID_MJPEG:
40
      return 4;
41
    case CODEC_ID_MPEG4:
42
      return 5;
43
    case CODEC_ID_FLV1:
44
      return 6;
45
    case CODEC_ID_SVQ3:
46
      return 7;
47
    case CODEC_ID_DVVIDEO:
48
      return 8;
49
    case CODEC_ID_H264:
50
      return 9;
51
    case CODEC_ID_THEORA:
52
    case CODEC_ID_VP3:
53
      return 10;
54
    case CODEC_ID_SNOW:
55
      return 11;
56
    case CODEC_ID_VP6:
57
      return 12;
58
    case CODEC_ID_DIRAC:
59
      return 13;
60
    default:
61
      fprintf(stderr, "Unknown codec ID %d\n", cid);
62
      return 0;
63
  }
64
}
65

    
66
static void video_header_fill(uint8_t *data, AVStream *st)
67
{
68
  int num, den;
69

    
70
  data[0] = codec_type(st->codec->codec_id);
71
  data[1] = st->codec->width >> 8;
72
  data[2] = st->codec->width & 0xFF;
73
  data[3] = st->codec->height >> 8;
74
  data[4] = st->codec->height & 0xFF;
75
  num = st->avg_frame_rate.num;
76
  den = st->avg_frame_rate.den;
77
//fprintf(stderr, "Rate: %d/%d\n", num, den);
78
  if (num == 0) {
79
    num = st->r_frame_rate.num;
80
    den = st->r_frame_rate.den;
81
  }
82
  if (num > (1 << 16)) {
83
    num /= 1000;
84
    den /= 1000;
85
  }
86
  data[5] = num >> 8;
87
  data[6] = num & 0xFF;
88
  data[7] = den >> 8;
89
  data[8] = den & 0xFF;
90
}
91

    
92
static void frame_header_fill(uint8_t *data, int size, AVPacket *pkt, AVStream *st, int64_t base_ts)
93
{
94
  AVRational fps;
95
  int32_t pts, dts;
96

    
97
  data[0] = size >> 16;
98
  data[1] = size >> 8;
99
  data[2] = size & 0xFF;
100
  fps = st->avg_frame_rate;
101
  if (fps.num == 0) {
102
    fps = st->r_frame_rate;
103
  }
104
  pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){fps.den, fps.num}),
105
  pts += av_rescale_q(base_ts, AV_TIME_BASE_Q, (AVRational){fps.den, fps.num});
106
  dprintf("pkt->pts=%ld PTS=%d",pkt->pts, pts);
107
  dts = av_rescale_q(pkt->dts, st->time_base, (AVRational){fps.den, fps.num});
108
  dts += av_rescale_q(base_ts, AV_TIME_BASE_Q, (AVRational){fps.den, fps.num});
109
  dprintf(" DTS=%d\n",dts);
110
  data[3] = pts >> 24;
111
  data[4] = pts >> 16;
112
  data[5] = pts >> 8;
113
  data[6] = pts & 0xFF;
114
  data[7] = (pts - dts) & 0xFF;
115
}
116

    
117
struct input_stream *input_stream_open(const char *fname, int *period, uint16_t flags)
118
{
119
  struct input_stream *desc;
120
  int i, res;
121

    
122
  avcodec_register_all();
123
  av_register_all();
124

    
125
  desc = malloc(sizeof(struct input_stream));
126
  if (desc == NULL) {
127
    return NULL;
128
  }
129
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
130
  if (res < 0) {
131
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
132

    
133
    return NULL;
134
  }
135

    
136
  res = av_find_stream_info(desc->s);
137
  if (res < 0) {
138
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
139

    
140
    return NULL;
141
  }
142
  desc->video_stream = -1;
143
  desc->audio_stream = -1;
144
  desc->last_ts = 0;
145
  desc->base_ts = 0;
146
  desc->frames_since_global_headers = 0;
147
  desc->loop = flags & INPUT_LOOP;
148
  for (i = 0; i < desc->s->nb_streams; i++) {
149
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
150
      desc->video_stream = i;
151
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
152
              desc->s->streams[i]->r_frame_rate.num,
153
              desc->s->streams[i]->r_frame_rate.den,
154
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
155
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
156
    }
157
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
158
      desc->audio_stream = i;
159
    }
160
  }
161

    
162
  dump_format(desc->s, 0, fname, 0);
163

    
164
  return desc;
165
}
166

    
167
void input_stream_close(struct input_stream *s)
168
{
169
    av_close_input_file(s->s);
170
    free(s);
171
}
172

    
173
int input_stream_rewind(struct input_stream *s)
174
{
175
    int ret;
176

    
177
    ret = av_seek_frame(s->s,-1,0,0);
178
    s->base_ts = s->last_ts;
179

    
180
    return ret;
181
}
182

    
183

    
184
#if 0
185
int input_get_1(struct input_stream *s, struct chunk *c)
186
{
187
    static AVPacket pkt;
188
    static int inited;
189
    AVStream *st;
190
    int res;
191
    static uint8_t static_buff[STATIC_BUFF_SIZE];
192
    static int cid;
193
    uint8_t *p;
194

195
    p = static_buff;
196
    if (inited == 0) {
197
        inited = 1;
198
        res = av_read_frame(s->s, &pkt);
199
        if (res < 0) {
200
            fprintf(stderr, "First read failed: %d!!!\n", res);
201

202
            return 0;
203
        }
204
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
205
            fprintf(stderr, "First frame is not key frame!!!\n");
206

207
            return 0;
208
        }
209
    }
210
    c->timestamp = pkt.dts;
211
    memcpy(p, pkt.data, pkt.size);
212
    p += pkt.size;
213
    while (1) {
214
        res = av_read_frame(s->s, &pkt);
215
        if (res >= 0) {
216
            st = s->s->streams[pkt.stream_index];
217
            if (pkt.flags & PKT_FLAG_KEY) {
218
                c->size = p - static_buff;
219
                c->data = malloc(c->size);
220
                if (c->data == NULL) {
221
                  return 0;
222
                }
223
                memcpy(c->data, static_buff, c->size);
224
                c->attributes_size = 0;
225
                c->attributes = NULL;
226
                c->id = cid++; 
227
                return 1;
228
            }
229
            memcpy(p, pkt.data, pkt.size);
230
            p += pkt.size;
231
        } else {
232
            if (p - static_buff > 0) {
233
                c->size = p - static_buff;
234
                c->data = malloc(c->size);
235
                if (c->data == NULL) {
236
                  return 0;
237
                }
238
                memcpy(c->data, static_buff, c->size);
239
                c->attributes_size = 0;
240
                c->attributes = NULL;
241
                c->id = cid++; 
242
                return 1;
243
            }
244
            return 0;
245
        }
246
    }
247

248
    return 0;
249
}
250
#endif
251

    
252
uint8_t *chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
253
{
254
    AVPacket pkt;
255
    int res;
256
    uint8_t *data;
257
    int header_out, header_size;
258

    
259
    res = av_read_frame(s->s, &pkt);
260
    if (res < 0) {
261
      if (s->loop) {
262
        if (input_stream_rewind(s) >= 0) {
263
          *size = 0;
264
          *ts = s->last_ts;
265

    
266
          return NULL;
267
        }
268
      }
269
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
270
      *size = -1;
271

    
272
      return NULL;
273
    }
274
    if (pkt.stream_index != s->video_stream) {
275
      *size = 0;
276
      *ts = s->last_ts;
277
      av_free_packet(&pkt);
278

    
279
      return NULL;
280
    }
281

    
282
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
283
      header_size = VIDEO_PAYLOAD_HEADER_SIZE;
284
    }
285
    header_out = (pkt.flags & PKT_FLAG_KEY) != 0;
286
    if (header_out == 0) {
287
      s->frames_since_global_headers++;
288
      if (s->frames_since_global_headers == HEADER_REFRESH_PERIOD) {
289
        s->frames_since_global_headers = 0;
290
        header_out = 1;
291
      }
292
    }
293
    *size = pkt.size + s->s->streams[pkt.stream_index]->codec->extradata_size * header_out + header_size + FRAME_HEADER_SIZE;
294
    data = malloc(*size);
295
    if (data == NULL) {
296
      *size = -1;
297
      av_free_packet(&pkt);
298

    
299
      return NULL;
300
    }
301
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
302
      video_header_fill(data, s->s->streams[pkt.stream_index]);
303
    }
304
    data[VIDEO_PAYLOAD_HEADER_SIZE - 1] = 1;
305
    frame_header_fill(data + VIDEO_PAYLOAD_HEADER_SIZE, *size - header_size - FRAME_HEADER_SIZE, &pkt, s->s->streams[pkt.stream_index], s->base_ts);
306

    
307
    if (header_out && s->s->streams[pkt.stream_index]->codec->extradata_size) {
308
      memcpy(data + header_size + FRAME_HEADER_SIZE, s->s->streams[pkt.stream_index]->codec->extradata, s->s->streams[pkt.stream_index]->codec->extradata_size);
309
      memcpy(data + header_size + FRAME_HEADER_SIZE + s->s->streams[pkt.stream_index]->codec->extradata_size, pkt.data, pkt.size);
310
    } else {
311
      memcpy(data + header_size + FRAME_HEADER_SIZE, pkt.data, pkt.size);
312
    }
313
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
314
    dprintf("pkt.dts=%ld TS1=%lu" , pkt.dts, *ts);
315
    *ts += s->base_ts;
316
    dprintf(" TS2=%lu\n",*ts);
317
    s->last_ts = *ts;
318
    av_free_packet(&pkt);
319

    
320
    return data;
321
}
322

    
323
#if 0
324
int chunk_read_avs1(void *s_h, struct chunk *c)
325
{
326
    AVFormatContext *s = s_h;
327
    static AVPacket pkt;
328
    static int inited;
329
    AVStream *st;
330
    int res;
331
    int cnt;
332
    static uint8_t static_buff[STATIC_BUFF_SIZE];
333
    uint8_t *p, *pcurr;
334
    static uint8_t *p1;
335
    static struct chunk c2;
336
    int f1;
337
    static int f2;
338

339
    if (p1) {
340
        c2.id = c->id;
341
        *c = c2;
342
        p1 = NULL;
343

344
        return f2;
345
    }
346

347
    p = static_buff;
348
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
349
    if (inited == 0) {
350
        inited = 1;
351
        res = av_read_frame(s, &pkt);
352
        if (res < 0) {
353
            fprintf(stderr, "First read failed: %d!!!\n", res);
354

355
            return 0;
356
        }
357
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
358
            fprintf(stderr, "First frame is not key frame!!!\n");
359

360
            return 0;
361
        }
362
    }
363
    cnt = 0; f1 = 0; f2 = 0;
364
    c->stride_size = 2;
365
    c2.stride_size = 2;
366
    pcurr = p1;
367
    if (pkt.size > 0) {
368
        memcpy(p, pkt.data, pkt.size);
369
        c->frame[0] = p;
370
        c->frame_len[0] = pkt.size;
371
        f1++;
372
        p += pkt.size;
373
    }
374
    while (1) {
375
        res = av_read_frame(s, &pkt);
376
        if (res >= 0) {
377
            st = s->streams[pkt.stream_index];
378
            if (pkt.flags & PKT_FLAG_KEY) {
379
                cnt++;
380
                if (cnt == 2) {
381
                    return f1;
382
                }
383
            }
384
            memcpy(pcurr, pkt.data, pkt.size);
385
            if (pcurr == p) {
386
                c->frame[f1] = pcurr;
387
                c->frame_len[f1] = pkt.size;
388
                p += pkt.size;
389
                pcurr = p1;
390
                f1++;
391
            } else {
392
                c2.frame[f2] = pcurr;
393
                c2.frame_len[f2] = pkt.size;
394
                p1 += pkt.size;
395
                pcurr = p;
396
                f2++;
397
            }
398
        } else {
399
            pkt.size = 0;
400

401
            return f1;
402
        }
403
    }
404

405
    return 0;
406
}
407
#endif