Statistics
| Branch: | Revision:

grapes / src / Chunkiser / input-stream-avf.c @ 1cc19859

History | View | Annotate | Download (9.23 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 input_stream {
17
  AVFormatContext *s;
18
  int 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
  AVBitStreamFilterContext *bsf[MAX_STREAMS];
24
};
25

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

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

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

    
82
static void frame_header_fill(uint8_t *data, int size, AVPacket *pkt, AVStream *st, int64_t base_ts)
83
{
84
  AVRational fps;
85
  int32_t pts, dts;
86

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

    
109
static int input_stream_rewind(struct input_stream *s)
110
{
111
    int ret;
112

    
113
    ret = av_seek_frame(s->s,-1,0,0);
114
    s->base_ts = s->last_ts;
115

    
116
    return ret;
117
}
118

    
119

    
120
/* Interface functions */
121

    
122
static struct input_stream *avf_open(const char *fname, int *period, const char *config)
123
{
124
  struct input_stream *desc;
125
  int i, res;
126
  struct tag *cfg_tags;
127

    
128
  avcodec_register_all();
129
  av_register_all();
130

    
131
  desc = malloc(sizeof(struct input_stream));
132
  if (desc == NULL) {
133
    return NULL;
134
  }
135
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
136
  if (res < 0) {
137
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
138

    
139
    return NULL;
140
  }
141

    
142
  desc->s->flags |= AVFMT_FLAG_GENPTS;
143
  res = av_find_stream_info(desc->s);
144
  if (res < 0) {
145
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
146

    
147
    return NULL;
148
  }
149
  desc->video_stream = -1;
150
  desc->audio_stream = -1;
151
  desc->last_ts = 0;
152
  desc->base_ts = 0;
153
  desc->loop = 0;
154
  cfg_tags = config_parse(config);
155
  if (cfg_tags) {
156
    config_value_int(cfg_tags, "loop", &desc->loop);
157
  }
158
  for (i = 0; i < desc->s->nb_streams; i++) {
159
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
160
      desc->video_stream = i;
161
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
162
              desc->s->streams[i]->r_frame_rate.num,
163
              desc->s->streams[i]->r_frame_rate.den,
164
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
165
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
166
    }
167
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
168
      desc->audio_stream = i;
169
    }
170
    if (desc->s->streams[i]->codec->codec_id == CODEC_ID_MPEG4) {
171
      desc->bsf[i] = av_bitstream_filter_init("dump_extra");
172
    } else if (desc->s->streams[i]->codec->codec_id == CODEC_ID_H264) {
173
      desc->bsf[i] = av_bitstream_filter_init("h264_mp4toannexb");
174
    } else {
175
      desc->bsf[i] = NULL;
176
    }
177
  }
178

    
179
  dump_format(desc->s, 0, fname, 0);
180

    
181
  return desc;
182
}
183

    
184
static void avf_close(struct input_stream *s)
185
{
186
  int i;
187

    
188
  for (i = 0; i < s->s->nb_streams; i++) {
189
    if (s->bsf[i]) {
190
      av_bitstream_filter_close(s->bsf[i]);
191
    }
192
  }
193
  av_close_input_file(s->s);
194
  free(s);
195
}
196

    
197
static uint8_t *avf_chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
198
{
199
    AVPacket pkt;
200
    int res;
201
    uint8_t *data;
202
    int header_size;
203

    
204
    res = av_read_frame(s->s, &pkt);
205
    if (res < 0) {
206
      if (s->loop) {
207
        if (input_stream_rewind(s) >= 0) {
208
          *size = 0;
209
          *ts = s->last_ts;
210

    
211
          return NULL;
212
        }
213
      }
214
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
215
      *size = -1;
216

    
217
      return NULL;
218
    }
219
    if (pkt.stream_index != s->video_stream) {
220
      *size = 0;
221
      *ts = s->last_ts;
222
      av_free_packet(&pkt);
223

    
224
      return NULL;
225
    }
226
    if (s->bsf[pkt.stream_index]) {
227
      AVPacket new_pkt= pkt;
228
      int res;
229

    
230
      res = av_bitstream_filter_filter(s->bsf[pkt.stream_index],
231
                                       s->s->streams[pkt.stream_index]->codec,
232
                                       NULL, &new_pkt.data, &new_pkt.size,
233
                                       pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY);
234
      if(res > 0){
235
        av_free_packet(&pkt);
236
        new_pkt.destruct= av_destruct_packet;
237
      } else if(res < 0){
238
        fprintf(stderr, "%s failed for stream %d, codec %s: ",
239
                        s->bsf[pkt.stream_index]->filter->name,
240
                        pkt.stream_index,
241
                        s->s->streams[pkt.stream_index]->codec->codec->name);
242
        fprintf(stderr, "%d\n", res);
243
        *size = 0;
244

    
245
        return NULL;
246
      }
247
      pkt= new_pkt;
248
    }
249

    
250
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
251
      header_size = VIDEO_PAYLOAD_HEADER_SIZE;
252
    }
253
    *size = pkt.size + header_size + FRAME_HEADER_SIZE;
254
    data = malloc(*size);
255
    if (data == NULL) {
256
      *size = -1;
257
      av_free_packet(&pkt);
258

    
259
      return NULL;
260
    }
261
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
262
      video_header_fill(data, s->s->streams[pkt.stream_index]);
263
    }
264
    data[VIDEO_PAYLOAD_HEADER_SIZE - 1] = 1;
265
    frame_header_fill(data + VIDEO_PAYLOAD_HEADER_SIZE, *size - header_size - FRAME_HEADER_SIZE, &pkt, s->s->streams[pkt.stream_index], s->base_ts);
266

    
267
    memcpy(data + header_size + FRAME_HEADER_SIZE, pkt.data, pkt.size);
268
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
269
    //dprintf("pkt.dts=%ld TS1=%lu" , pkt.dts, *ts);
270
    *ts += s->base_ts;
271
    //dprintf(" TS2=%lu\n",*ts);
272
    s->last_ts = *ts;
273
    av_free_packet(&pkt);
274

    
275
    return data;
276
}
277

    
278
#if 0
279
int chunk_read_avs1(void *s_h, struct chunk *c)
280
{
281
    AVFormatContext *s = s_h;
282
    static AVPacket pkt;
283
    static int inited;
284
    AVStream *st;
285
    int res;
286
    int cnt;
287
    static uint8_t static_buff[STATIC_BUFF_SIZE];
288
    uint8_t *p, *pcurr;
289
    static uint8_t *p1;
290
    static struct chunk c2;
291
    int f1;
292
    static int f2;
293

294
    if (p1) {
295
        c2.id = c->id;
296
        *c = c2;
297
        p1 = NULL;
298

299
        return f2;
300
    }
301

302
    p = static_buff;
303
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
304
    if (inited == 0) {
305
        inited = 1;
306
        res = av_read_frame(s, &pkt);
307
        if (res < 0) {
308
            fprintf(stderr, "First read failed: %d!!!\n", res);
309

310
            return 0;
311
        }
312
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
313
            fprintf(stderr, "First frame is not key frame!!!\n");
314

315
            return 0;
316
        }
317
    }
318
    cnt = 0; f1 = 0; f2 = 0;
319
    c->stride_size = 2;
320
    c2.stride_size = 2;
321
    pcurr = p1;
322
    if (pkt.size > 0) {
323
        memcpy(p, pkt.data, pkt.size);
324
        c->frame[0] = p;
325
        c->frame_len[0] = pkt.size;
326
        f1++;
327
        p += pkt.size;
328
    }
329
    while (1) {
330
        res = av_read_frame(s, &pkt);
331
        if (res >= 0) {
332
            st = s->streams[pkt.stream_index];
333
            if (pkt.flags & PKT_FLAG_KEY) {
334
                cnt++;
335
                if (cnt == 2) {
336
                    return f1;
337
                }
338
            }
339
            memcpy(pcurr, pkt.data, pkt.size);
340
            if (pcurr == p) {
341
                c->frame[f1] = pcurr;
342
                c->frame_len[f1] = pkt.size;
343
                p += pkt.size;
344
                pcurr = p1;
345
                f1++;
346
            } else {
347
                c2.frame[f2] = pcurr;
348
                c2.frame_len[f2] = pkt.size;
349
                p1 += pkt.size;
350
                pcurr = p;
351
                f2++;
352
            }
353
        } else {
354
            pkt.size = 0;
355

356
            return f1;
357
        }
358
    }
359

360
    return 0;
361
}
362
#endif
363

    
364
struct chunkiser_iface in_avf = {
365
  .open = avf_open,
366
  .close = avf_close,
367
  .chunkise = avf_chunkise,
368
};