Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ bec77fd1

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 "../input.h"                //TODO: for flags. Check if we can do something smarter
13
#define STATIC_BUFF_SIZE 1000 * 1024
14
#define HEADER_REFRESH_PERIOD 50
15

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

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

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

    
120
  avcodec_register_all();
121
  av_register_all();
122

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

    
131
    return NULL;
132
  }
133

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

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

    
160
  dump_format(desc->s, 0, fname, 0);
161

    
162
  return desc;
163
}
164

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

    
171
int input_stream_rewind(struct input_stream *s)
172
{
173
    int ret;
174

    
175
    ret = av_seek_frame(s->s,-1,0,0);
176
    s->base_ts = s->last_ts;
177

    
178
    return ret;
179
}
180

    
181

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

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

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

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

246
    return 0;
247
}
248
#endif
249

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

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

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

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

    
277
      return NULL;
278
    }
279

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

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

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

    
318
    return data;
319
}
320

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

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

342
        return f2;
343
    }
344

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

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

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

399
            return f1;
400
        }
401
    }
402

403
    return 0;
404
}
405
#endif