Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 84ff82ba

History | View | Annotate | Download (10.5 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
static int header_refresh_period;
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
      header_refresh_period = 50;
43
      return 5;
44
    case CODEC_ID_FLV1:
45
      return 6;
46
    case CODEC_ID_SVQ3:
47
      return 7;
48
    case CODEC_ID_DVVIDEO:
49
      return 8;
50
    case CODEC_ID_H264:
51
      header_refresh_period = 50;
52
      return 9;
53
    case CODEC_ID_THEORA:
54
    case CODEC_ID_VP3:
55
      return 10;
56
    case CODEC_ID_SNOW:
57
      return 11;
58
    case CODEC_ID_VP6:
59
      return 12;
60
    case CODEC_ID_DIRAC:
61
      return 13;
62
    default:
63
      fprintf(stderr, "Unknown codec ID %d\n", cid);
64
      return 0;
65
  }
66
}
67

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

    
72
  num = st->avg_frame_rate.num;
73
  den = st->avg_frame_rate.den;
74
//fprintf(stderr, "Rate: %d/%d\n", num, den);
75
  if (num == 0) {
76
    num = st->r_frame_rate.num;
77
    den = st->r_frame_rate.den;
78
  }
79
  if (num > (1 << 16)) {
80
    num /= 1000;
81
    den /= 1000;
82
  }
83
  payload_header_write(data, codec_type(st->codec->codec_id), st->codec->width, st->codec->height, num, den);
84
}
85

    
86
static void frame_header_fill(uint8_t *data, int size, AVPacket *pkt, AVStream *st, int64_t base_ts)
87
{
88
  AVRational fps;
89
  int32_t pts, dts;
90

    
91
  fps = st->avg_frame_rate;
92
  if (fps.num == 0) {
93
    fps = st->r_frame_rate;
94
  }
95
  if (pkt->pts != AV_NOPTS_VALUE) {
96
    pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){fps.den, fps.num}),
97
    pts += av_rescale_q(base_ts, AV_TIME_BASE_Q, (AVRational){fps.den, fps.num});
98
  } else {
99
    pts = -1;
100
  }
101
  dprintf("pkt->pts=%ld PTS=%d",pkt->pts, pts);
102
  if (pkt->dts != AV_NOPTS_VALUE) {
103
    dts = av_rescale_q(pkt->dts, st->time_base, (AVRational){fps.den, fps.num});
104
    dts += av_rescale_q(base_ts, AV_TIME_BASE_Q, (AVRational){fps.den, fps.num});
105
  } else {
106
    fprintf(stderr, "No DTS???\n");
107
    dts = 0;
108
  }
109
  dprintf(" DTS=%d\n",dts);
110
  frame_header_write(data, size, pts, dts);
111
}
112

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

    
118
  avcodec_register_all();
119
  av_register_all();
120

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

    
129
    return NULL;
130
  }
131

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

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

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

    
161
  return desc;
162
}
163

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

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

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

    
177
    return ret;
178
}
179

    
180

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

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

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

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

245
    return 0;
246
}
247
#endif
248

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

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

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

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

    
276
      return NULL;
277
    }
278

    
279
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
280
      header_size = VIDEO_PAYLOAD_HEADER_SIZE;
281
    }
282
    if (header_refresh_period) {
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
    } else {
292
      header_out = 0;
293
    }
294
    *size = pkt.size + s->s->streams[pkt.stream_index]->codec->extradata_size * header_out + header_size + FRAME_HEADER_SIZE;
295
    data = malloc(*size);
296
    if (data == NULL) {
297
      *size = -1;
298
      av_free_packet(&pkt);
299

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

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

    
321
    return data;
322
}
323

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

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

345
        return f2;
346
    }
347

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

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

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

402
            return f1;
403
        }
404
    }
405

406
    return 0;
407
}
408
#endif