Statistics
| Branch: | Revision:

grapes / src / Chunkiser / input-stream-avf.c @ 4cdd16a7

History | View | Annotate | Download (10.7 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 "payload.h"
12
#include "config.h"
13
#include "chunkiser_iface.h"
14

    
15
#define STATIC_BUFF_SIZE 1000 * 1024
16
struct chunkiser_ctx {
17
  AVFormatContext *s;
18
  int loop;        //loop on input file infinitely
19
  uint64_t streams;
20
  int64_t last_ts;
21
  int64_t base_ts;
22
  AVBitStreamFilterContext *bsf[MAX_STREAMS];
23
};
24

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

    
72
static void audio_header_fill(uint8_t *data, AVStream *st)
73
{
74
  audio_payload_header_write(data, codec_type(st->codec->codec_id), st->codec->channels, st->codec->sample_rate, st->codec->frame_size);
75
}
76

    
77
static void video_header_fill(uint8_t *data, AVStream *st)
78
{
79
  int num, den;
80

    
81
  num = st->avg_frame_rate.num;
82
  den = st->avg_frame_rate.den;
83
//fprintf(stderr, "Rate: %d/%d\n", num, den);
84
  if (num == 0) {
85
    num = st->r_frame_rate.num;
86
    den = st->r_frame_rate.den;
87
  }
88
  if (num > (1 << 16)) {
89
    num /= 1000;
90
    den /= 1000;
91
  }
92
  video_payload_header_write(data, codec_type(st->codec->codec_id), st->codec->width, st->codec->height, num, den);
93
}
94

    
95
static void frame_header_fill(uint8_t *data, int size, AVPacket *pkt, AVStream *st, AVRational new_tb, int64_t base_ts)
96
{
97
  int32_t pts, dts;
98

    
99
  if (pkt->pts != AV_NOPTS_VALUE) {
100
    pts = av_rescale_q(pkt->pts, st->time_base, new_tb),
101
    pts += av_rescale_q(base_ts, AV_TIME_BASE_Q, new_tb);
102
  } else {
103
    pts = -1;
104
  }
105
  //dprintf("pkt->pts=%ld PTS=%d",pkt->pts, pts);
106
  if (pkt->dts != AV_NOPTS_VALUE) {
107
    dts = av_rescale_q(pkt->dts, st->time_base, new_tb);
108
    dts += av_rescale_q(base_ts, AV_TIME_BASE_Q, new_tb);
109
  } else {
110
    fprintf(stderr, "No DTS???\n");
111
    dts = 0;
112
  }
113
  //dprintf(" DTS=%d\n",dts);
114
  frame_header_write(data, size, pts, dts);
115
}
116

    
117
static int input_stream_rewind(struct chunkiser_ctx *s)
118
{
119
  int ret;
120

    
121
  ret = av_seek_frame(s->s,-1,0,0);
122
  s->base_ts = s->last_ts;
123

    
124
  return ret;
125
}
126

    
127

    
128
/* Interface functions */
129

    
130
static struct chunkiser_ctx *avf_open(const char *fname, int *period, const char *config)
131
{
132
  struct chunkiser_ctx *desc;
133
  int i, res;
134
  struct tag *cfg_tags;
135
  int video_streams = 0, audio_streams = 1;
136

    
137
  avcodec_register_all();
138
  av_register_all();
139

    
140
  desc = malloc(sizeof(struct chunkiser_ctx));
141
  if (desc == NULL) {
142
    return NULL;
143
  }
144
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
145
  if (res < 0) {
146
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
147

    
148
    return NULL;
149
  }
150

    
151
  desc->s->flags |= AVFMT_FLAG_GENPTS;
152
  res = av_find_stream_info(desc->s);
153
  if (res < 0) {
154
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
155

    
156
    return NULL;
157
  }
158
  desc->streams = 0;
159
  desc->last_ts = 0;
160
  desc->base_ts = 0;
161
  desc->loop = 0;
162
  cfg_tags = config_parse(config);
163
  if (cfg_tags) {
164
    const char *media;
165

    
166
    config_value_int(cfg_tags, "loop", &desc->loop);
167
    media = config_value_str(cfg_tags, "media");
168
    if (media) {
169
      if (!strcmp(media, "audio")) {
170
        audio_streams = 0;
171
        video_streams = 1;
172
      } else if (!strcmp(media, "video")) {
173
        audio_streams = 1;
174
        video_streams = 0;
175
      } else if (!strcmp(media, "av")) {
176
        audio_streams = 0;
177
        video_streams = 0;
178
      }
179
    }
180
  }
181
  free(cfg_tags);
182
  for (i = 0; i < desc->s->nb_streams; i++) {
183
    if (desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
184
      if (video_streams++ == 0) {
185
        desc->streams |= 1ULL << i;
186
      }
187
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
188
              desc->s->streams[i]->r_frame_rate.num,
189
              desc->s->streams[i]->r_frame_rate.den,
190
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
191
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
192
    }
193
    if (desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
194
      if (audio_streams++ == 0) {
195
        desc->streams |= 1ULL << i;
196
      }
197
    }
198
    if (desc->s->streams[i]->codec->codec_id == CODEC_ID_MPEG4) {
199
      desc->bsf[i] = av_bitstream_filter_init("dump_extra");
200
    } else if (desc->s->streams[i]->codec->codec_id == CODEC_ID_H264) {
201
      desc->bsf[i] = av_bitstream_filter_init("h264_mp4toannexb");
202
    } else {
203
      desc->bsf[i] = NULL;
204
    }
205
  }
206

    
207
  dump_format(desc->s, 0, fname, 0);
208

    
209
  return desc;
210
}
211

    
212
static void avf_close(struct chunkiser_ctx *s)
213
{
214
  int i;
215

    
216
  for (i = 0; i < s->s->nb_streams; i++) {
217
    if (s->bsf[i]) {
218
      av_bitstream_filter_close(s->bsf[i]);
219
    }
220
  }
221
  av_close_input_file(s->s);
222
  free(s);
223
}
224

    
225
static uint8_t *avf_chunkise(struct chunkiser_ctx *s, int id, int *size, uint64_t *ts)
226
{
227
  AVPacket pkt;
228
  AVRational new_tb;
229
  int res;
230
  uint8_t *data;
231
  int header_size;
232

    
233
  res = av_read_frame(s->s, &pkt);
234
  if (res < 0) {
235
    if (s->loop) {
236
      if (input_stream_rewind(s) >= 0) {
237
        *size = 0;
238
        *ts = s->last_ts;
239

    
240
        return NULL;
241
      }
242
    }
243
    fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
244
    *size = -1;
245

    
246
    return NULL;
247
  }
248
  if ((s->streams & (1ULL << pkt.stream_index)) == 0) {
249
    *size = 0;
250
    *ts = s->last_ts;
251
    av_free_packet(&pkt);
252

    
253
    return NULL;
254
  }
255
  if (s->bsf[pkt.stream_index]) {
256
    AVPacket new_pkt= pkt;
257
    int res;
258

    
259
    res = av_bitstream_filter_filter(s->bsf[pkt.stream_index],
260
                                     s->s->streams[pkt.stream_index]->codec,
261
                                     NULL, &new_pkt.data, &new_pkt.size,
262
                                     pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY);
263
    if(res > 0){
264
      av_free_packet(&pkt);
265
      new_pkt.destruct= av_destruct_packet;
266
    } else if(res < 0){
267
      fprintf(stderr, "%s failed for stream %d, codec %s: ",
268
                      s->bsf[pkt.stream_index]->filter->name,
269
                      pkt.stream_index,
270
                      s->s->streams[pkt.stream_index]->codec->codec->name);
271
      fprintf(stderr, "%d\n", res);
272
      *size = 0;
273

    
274
      return NULL;
275
    }
276
    pkt= new_pkt;
277
  }
278

    
279
  switch (s->s->streams[pkt.stream_index]->codec->codec_type) {
280
    case CODEC_TYPE_VIDEO:
281
      header_size = VIDEO_PAYLOAD_HEADER_SIZE;
282
      break;
283
    case CODEC_TYPE_AUDIO:
284
      header_size = AUDIO_PAYLOAD_HEADER_SIZE;
285
      break;
286
    default:
287
      /* Cannot arrive here... */
288
      fprintf(stderr, "Internal chunkiser error!\n");
289
      exit(-1);
290
  }
291
  *size = pkt.size + header_size + FRAME_HEADER_SIZE;
292
  data = malloc(*size);
293
  if (data == NULL) {
294
    *size = -1;
295
    av_free_packet(&pkt);
296

    
297
    return NULL;
298
  }
299
  switch (s->s->streams[pkt.stream_index]->codec->codec_type) {
300
    case CODEC_TYPE_VIDEO:
301
      video_header_fill(data, s->s->streams[pkt.stream_index]);
302
      new_tb.den = s->s->streams[pkt.stream_index]->avg_frame_rate.num;
303
      new_tb.num = s->s->streams[pkt.stream_index]->avg_frame_rate.den;
304
      if (new_tb.num == 0) {
305
        new_tb.den = s->s->streams[pkt.stream_index]->r_frame_rate.num;
306
        new_tb.num = s->s->streams[pkt.stream_index]->r_frame_rate.den;
307
      }
308
      break;
309
    case CODEC_TYPE_AUDIO:
310
      audio_header_fill(data, s->s->streams[pkt.stream_index]);
311
      new_tb = (AVRational){s->s->streams[pkt.stream_index]->codec->frame_size, s->s->streams[pkt.stream_index]->codec->sample_rate};
312
      break;
313
    default:
314
      /* Cannot arrive here... */
315
      fprintf(stderr, "Internal chunkiser error!\n");
316
      exit(-1);
317
  }
318
  data[header_size - 1] = 1;
319
  frame_header_fill(data + header_size, *size - header_size - FRAME_HEADER_SIZE, &pkt, s->s->streams[pkt.stream_index], new_tb, s->base_ts);
320

    
321
  memcpy(data + header_size + FRAME_HEADER_SIZE, pkt.data, pkt.size);
322
  *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
323
  //dprintf("pkt.dts=%ld TS1=%lu" , pkt.dts, *ts);
324
  *ts += s->base_ts;
325
  //dprintf(" TS2=%lu\n",*ts);
326
  s->last_ts = *ts;
327
  av_free_packet(&pkt);
328

    
329
  return data;
330
}
331

    
332
#if 0
333
int chunk_read_avs1(void *s_h, struct chunk *c)
334
{
335
    AVFormatContext *s = s_h;
336
    static AVPacket pkt;
337
    static int inited;
338
    AVStream *st;
339
    int res;
340
    int cnt;
341
    static uint8_t static_buff[STATIC_BUFF_SIZE];
342
    uint8_t *p, *pcurr;
343
    static uint8_t *p1;
344
    static struct chunk c2;
345
    int f1;
346
    static int f2;
347

348
    if (p1) {
349
        c2.id = c->id;
350
        *c = c2;
351
        p1 = NULL;
352

353
        return f2;
354
    }
355

356
    p = static_buff;
357
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
358
    if (inited == 0) {
359
        inited = 1;
360
        res = av_read_frame(s, &pkt);
361
        if (res < 0) {
362
            fprintf(stderr, "First read failed: %d!!!\n", res);
363

364
            return 0;
365
        }
366
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
367
            fprintf(stderr, "First frame is not key frame!!!\n");
368

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

410
            return f1;
411
        }
412
    }
413

414
    return 0;
415
}
416
#endif
417

    
418
struct chunkiser_iface in_avf = {
419
  .open = avf_open,
420
  .close = avf_close,
421
  .chunkise = avf_chunkise,
422
};