Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 87c82f76

History | View | Annotate | Download (10.2 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
#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
26

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

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

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

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

    
96
  data[0] = size >> 8;
97
  data[1] = size & 0xFF;
98
  fps = st->avg_frame_rate;
99
  if (fps.num == 0) {
100
    fps = st->r_frame_rate;
101
  }
102
  pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){fps.den, fps.num}),
103
  pts += av_rescale_q(base_ts, AV_TIME_BASE_Q, (AVRational){fps.den, fps.num});
104
  dts = av_rescale_q(pkt->dts, st->time_base, (AVRational){fps.den, fps.num});
105
  dts += av_rescale_q(base_ts, AV_TIME_BASE_Q, (AVRational){fps.den, fps.num});
106
  data[2] = pts >> 8;
107
  data[3] = pts & 0xFF;
108
  data[4] = dts >> 8;
109
  data[5] = dts & 0xFF;
110
}
111

    
112
struct input_stream *input_stream_open(const char *fname, int *period, uint16_t flags)
113
{
114
  struct input_stream *desc;
115
  int i, res;
116

    
117
  avcodec_register_all();
118
  av_register_all();
119

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

    
128
    return NULL;
129
  }
130

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

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

    
157
  dump_format(desc->s, 0, fname, 0);
158

    
159
  return desc;
160
}
161

    
162
void input_stream_close(struct input_stream *s)
163
{
164
    av_close_input_file(s->s);
165
    free(s);
166
}
167

    
168
int input_stream_rewind(struct input_stream *s)
169
{
170
    int ret;
171

    
172
    ret = av_seek_frame(s->s,-1,0,0);
173
    s->base_ts = s->last_ts;
174

    
175
    return ret;
176
}
177

    
178

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

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

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

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

243
    return 0;
244
}
245
#endif
246

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

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

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

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

    
274
      return NULL;
275
    }
276

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

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

    
302
    if (header_out && s->s->streams[pkt.stream_index]->codec->extradata_size) {
303
      memcpy(data + header_size + 2 + 2 + 2, s->s->streams[pkt.stream_index]->codec->extradata, s->s->streams[pkt.stream_index]->codec->extradata_size);
304
      memcpy(data + header_size + 2 + 2 + 2 + s->s->streams[pkt.stream_index]->codec->extradata_size, pkt.data, pkt.size);
305
    } else {
306
      memcpy(data + header_size + 2 + 2 + 2, pkt.data, pkt.size);
307
    }
308
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
309
    *ts += s->base_ts;
310
    s->last_ts = *ts;
311
    av_free_packet(&pkt);
312

    
313
    return data;
314
}
315

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

332
    if (p1) {
333
        c2.id = c->id;
334
        *c = c2;
335
        p1 = NULL;
336

337
        return f2;
338
    }
339

340
    p = static_buff;
341
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
342
    if (inited == 0) {
343
        inited = 1;
344
        res = av_read_frame(s, &pkt);
345
        if (res < 0) {
346
            fprintf(stderr, "First read failed: %d!!!\n", res);
347

348
            return 0;
349
        }
350
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
351
            fprintf(stderr, "First frame is not key frame!!!\n");
352

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

394
            return f1;
395
        }
396
    }
397

398
    return 0;
399
}
400
#endif