Statistics
| Branch: | Revision:

grapes / src / Chunkiser / input-stream-avf.c @ a6497b4b

History | View | Annotate | Download (8.89 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 "chunkiser.h"
11
//#include "dbg.h"
12
#include "payload.h"
13
#include "config.h"
14
#include "chunkiser_iface.h"
15

    
16
#define STATIC_BUFF_SIZE 1000 * 1024
17
struct input_stream {
18
  AVFormatContext *s;
19
  bool loop;        //loop on input file infinitely
20
  int audio_stream;
21
  int video_stream;
22
  int64_t last_ts;
23
  int64_t base_ts;
24
  AVBitStreamFilterContext *bsf[MAX_STREAMS];
25
};
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
  num = st->avg_frame_rate.num;
70
  den = st->avg_frame_rate.den;
71
//fprintf(stderr, "Rate: %d/%d\n", num, den);
72
  if (num == 0) {
73
    num = st->r_frame_rate.num;
74
    den = st->r_frame_rate.den;
75
  }
76
  if (num > (1 << 16)) {
77
    num /= 1000;
78
    den /= 1000;
79
  }
80
  payload_header_write(data, codec_type(st->codec->codec_id), st->codec->width, st->codec->height, num, den);
81
}
82

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

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

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

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

    
117
    return ret;
118
}
119

    
120

    
121
/* Interface functions */
122

    
123
static struct input_stream *avf_open(const char *fname, int *period, const char *config)
124
{
125
  struct input_stream *desc;
126
  int i, res;
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;        // FIXME: Check config!
154
  for (i = 0; i < desc->s->nb_streams; i++) {
155
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
156
      desc->video_stream = i;
157
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
158
              desc->s->streams[i]->r_frame_rate.num,
159
              desc->s->streams[i]->r_frame_rate.den,
160
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
161
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
162
    }
163
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
164
      desc->audio_stream = i;
165
    }
166
    if (desc->s->streams[i]->codec->codec_id == CODEC_ID_MPEG4) {
167
      desc->bsf[i] = av_bitstream_filter_init("dump_extra");
168
    } else {
169
      desc->bsf[i] = NULL;
170
    }
171
  }
172

    
173
  dump_format(desc->s, 0, fname, 0);
174

    
175
  return desc;
176
}
177

    
178
static void avf_close(struct input_stream *s)
179
{
180
    av_close_input_file(s->s);
181
    free(s);
182
}
183

    
184
static uint8_t *avf_chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
185
{
186
    AVPacket pkt;
187
    int res;
188
    uint8_t *data;
189
    int header_size;
190

    
191
    res = av_read_frame(s->s, &pkt);
192
    if (res < 0) {
193
      if (s->loop) {
194
        if (input_stream_rewind(s) >= 0) {
195
          *size = 0;
196
          *ts = s->last_ts;
197

    
198
          return NULL;
199
        }
200
      }
201
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
202
      *size = -1;
203

    
204
      return NULL;
205
    }
206
    if (pkt.stream_index != s->video_stream) {
207
      *size = 0;
208
      *ts = s->last_ts;
209
      av_free_packet(&pkt);
210

    
211
      return NULL;
212
    }
213
    if (s->bsf[pkt.stream_index]) {
214
      AVPacket new_pkt= pkt;
215
      int res;
216

    
217
      res = av_bitstream_filter_filter(s->bsf[pkt.stream_index],
218
                                       s->s->streams[pkt.stream_index]->codec,
219
                                       NULL, &new_pkt.data, &new_pkt.size,
220
                                       pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY);
221
      if(res > 0){
222
        av_free_packet(&pkt);
223
        new_pkt.destruct= av_destruct_packet;
224
      } else if(res < 0){
225
        fprintf(stderr, "%s failed for stream %d, codec %s: ",
226
                        s->bsf[pkt.stream_index]->filter->name,
227
                        pkt.stream_index,
228
                        s->s->streams[pkt.stream_index]->codec->codec->name);
229
        fprintf(stderr, "%d\n", res);
230
        *size = 0;
231

    
232
        return NULL;
233
      }
234
      pkt= new_pkt;
235
    }
236

    
237
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
238
      header_size = VIDEO_PAYLOAD_HEADER_SIZE;
239
    }
240
    *size = pkt.size + header_size + FRAME_HEADER_SIZE;
241
    data = malloc(*size);
242
    if (data == NULL) {
243
      *size = -1;
244
      av_free_packet(&pkt);
245

    
246
      return NULL;
247
    }
248
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
249
      video_header_fill(data, s->s->streams[pkt.stream_index]);
250
    }
251
    data[VIDEO_PAYLOAD_HEADER_SIZE - 1] = 1;
252
    frame_header_fill(data + VIDEO_PAYLOAD_HEADER_SIZE, *size - header_size - FRAME_HEADER_SIZE, &pkt, s->s->streams[pkt.stream_index], s->base_ts);
253

    
254
    memcpy(data + header_size + FRAME_HEADER_SIZE, pkt.data, pkt.size);
255
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
256
    //dprintf("pkt.dts=%ld TS1=%lu" , pkt.dts, *ts);
257
    *ts += s->base_ts;
258
    //dprintf(" TS2=%lu\n",*ts);
259
    s->last_ts = *ts;
260
    av_free_packet(&pkt);
261

    
262
    return data;
263
}
264

    
265
#if 0
266
int chunk_read_avs1(void *s_h, struct chunk *c)
267
{
268
    AVFormatContext *s = s_h;
269
    static AVPacket pkt;
270
    static int inited;
271
    AVStream *st;
272
    int res;
273
    int cnt;
274
    static uint8_t static_buff[STATIC_BUFF_SIZE];
275
    uint8_t *p, *pcurr;
276
    static uint8_t *p1;
277
    static struct chunk c2;
278
    int f1;
279
    static int f2;
280

281
    if (p1) {
282
        c2.id = c->id;
283
        *c = c2;
284
        p1 = NULL;
285

286
        return f2;
287
    }
288

289
    p = static_buff;
290
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
291
    if (inited == 0) {
292
        inited = 1;
293
        res = av_read_frame(s, &pkt);
294
        if (res < 0) {
295
            fprintf(stderr, "First read failed: %d!!!\n", res);
296

297
            return 0;
298
        }
299
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
300
            fprintf(stderr, "First frame is not key frame!!!\n");
301

302
            return 0;
303
        }
304
    }
305
    cnt = 0; f1 = 0; f2 = 0;
306
    c->stride_size = 2;
307
    c2.stride_size = 2;
308
    pcurr = p1;
309
    if (pkt.size > 0) {
310
        memcpy(p, pkt.data, pkt.size);
311
        c->frame[0] = p;
312
        c->frame_len[0] = pkt.size;
313
        f1++;
314
        p += pkt.size;
315
    }
316
    while (1) {
317
        res = av_read_frame(s, &pkt);
318
        if (res >= 0) {
319
            st = s->streams[pkt.stream_index];
320
            if (pkt.flags & PKT_FLAG_KEY) {
321
                cnt++;
322
                if (cnt == 2) {
323
                    return f1;
324
                }
325
            }
326
            memcpy(pcurr, pkt.data, pkt.size);
327
            if (pcurr == p) {
328
                c->frame[f1] = pcurr;
329
                c->frame_len[f1] = pkt.size;
330
                p += pkt.size;
331
                pcurr = p1;
332
                f1++;
333
            } else {
334
                c2.frame[f2] = pcurr;
335
                c2.frame_len[f2] = pkt.size;
336
                p1 += pkt.size;
337
                pcurr = p;
338
                f2++;
339
            }
340
        } else {
341
            pkt.size = 0;
342

343
            return f1;
344
        }
345
    }
346

347
    return 0;
348
}
349
#endif
350

    
351
struct chunkiser_iface in_avf = {
352
  .open = avf_open,
353
  .close = avf_close,
354
  .chunkise = avf_chunkise,
355
};