Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (9.68 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
  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
  video_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, AVRational new_tb, int64_t base_ts)
83
{
84
  int32_t pts, dts;
85

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

    
104
static int input_stream_rewind(struct chunkiser_ctx *s)
105
{
106
    int ret;
107

    
108
    ret = av_seek_frame(s->s,-1,0,0);
109
    s->base_ts = s->last_ts;
110

    
111
    return ret;
112
}
113

    
114

    
115
/* Interface functions */
116

    
117
static struct chunkiser_ctx *avf_open(const char *fname, int *period, const char *config)
118
{
119
  struct chunkiser_ctx *desc;
120
  int i, res;
121
  struct tag *cfg_tags;
122

    
123
  avcodec_register_all();
124
  av_register_all();
125

    
126
  desc = malloc(sizeof(struct chunkiser_ctx));
127
  if (desc == NULL) {
128
    return NULL;
129
  }
130
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
131
  if (res < 0) {
132
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
133

    
134
    return NULL;
135
  }
136

    
137
  desc->s->flags |= AVFMT_FLAG_GENPTS;
138
  res = av_find_stream_info(desc->s);
139
  if (res < 0) {
140
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
141

    
142
    return NULL;
143
  }
144
  desc->video_stream = -1;
145
  desc->audio_stream = -1;
146
  desc->last_ts = 0;
147
  desc->base_ts = 0;
148
  desc->loop = 0;
149
  cfg_tags = config_parse(config);
150
  if (cfg_tags) {
151
    config_value_int(cfg_tags, "loop", &desc->loop);
152
  }
153
  free(cfg_tags);
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 if (desc->s->streams[i]->codec->codec_id == CODEC_ID_H264) {
169
      desc->bsf[i] = av_bitstream_filter_init("h264_mp4toannexb");
170
    } else {
171
      desc->bsf[i] = NULL;
172
    }
173
  }
174

    
175
  dump_format(desc->s, 0, fname, 0);
176

    
177
  return desc;
178
}
179

    
180
static void avf_close(struct chunkiser_ctx *s)
181
{
182
  int i;
183

    
184
  for (i = 0; i < s->s->nb_streams; i++) {
185
    if (s->bsf[i]) {
186
      av_bitstream_filter_close(s->bsf[i]);
187
    }
188
  }
189
  av_close_input_file(s->s);
190
  free(s);
191
}
192

    
193
static uint8_t *avf_chunkise(struct chunkiser_ctx *s, int id, int *size, uint64_t *ts)
194
{
195
    AVPacket pkt;
196
    AVRational new_tb;
197
    int res;
198
    uint8_t *data;
199
    int header_size;
200

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

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

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

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

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

    
242
        return NULL;
243
      }
244
      pkt= new_pkt;
245
    }
246

    
247
    switch (s->s->streams[pkt.stream_index]->codec->codec_type) {
248
      case CODEC_TYPE_VIDEO:
249
        header_size = VIDEO_PAYLOAD_HEADER_SIZE;
250
        break;
251
      default:
252
        /* Cannot arrive here... */
253
        fprintf(stderr, "Internal chunkiser error!\n");
254
        exit(-1);
255
    }
256
    *size = pkt.size + header_size + FRAME_HEADER_SIZE;
257
    data = malloc(*size);
258
    if (data == NULL) {
259
      *size = -1;
260
      av_free_packet(&pkt);
261

    
262
      return NULL;
263
    }
264
    switch (s->s->streams[pkt.stream_index]->codec->codec_type) {
265
      case CODEC_TYPE_VIDEO:
266
        video_header_fill(data, s->s->streams[pkt.stream_index]);
267
        new_tb = s->s->streams[pkt.stream_index]->avg_frame_rate;
268
        if (new_tb.num == 0) {
269
          new_tb = s->s->streams[pkt.stream_index]->r_frame_rate;
270
        }
271
        break;
272
      default:
273
        /* Cannot arrive here... */
274
        fprintf(stderr, "Internal chunkiser error!\n");
275
        exit(-1);
276
    }
277
    data[header_size - 1] = 1;
278
    frame_header_fill(data + header_size, *size - header_size - FRAME_HEADER_SIZE, &pkt, s->s->streams[pkt.stream_index], new_tb, s->base_ts);
279

    
280
    memcpy(data + header_size + FRAME_HEADER_SIZE, pkt.data, pkt.size);
281
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
282
    //dprintf("pkt.dts=%ld TS1=%lu" , pkt.dts, *ts);
283
    *ts += s->base_ts;
284
    //dprintf(" TS2=%lu\n",*ts);
285
    s->last_ts = *ts;
286
    av_free_packet(&pkt);
287

    
288
    return data;
289
}
290

    
291
#if 0
292
int chunk_read_avs1(void *s_h, struct chunk *c)
293
{
294
    AVFormatContext *s = s_h;
295
    static AVPacket pkt;
296
    static int inited;
297
    AVStream *st;
298
    int res;
299
    int cnt;
300
    static uint8_t static_buff[STATIC_BUFF_SIZE];
301
    uint8_t *p, *pcurr;
302
    static uint8_t *p1;
303
    static struct chunk c2;
304
    int f1;
305
    static int f2;
306

307
    if (p1) {
308
        c2.id = c->id;
309
        *c = c2;
310
        p1 = NULL;
311

312
        return f2;
313
    }
314

315
    p = static_buff;
316
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
317
    if (inited == 0) {
318
        inited = 1;
319
        res = av_read_frame(s, &pkt);
320
        if (res < 0) {
321
            fprintf(stderr, "First read failed: %d!!!\n", res);
322

323
            return 0;
324
        }
325
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
326
            fprintf(stderr, "First frame is not key frame!!!\n");
327

328
            return 0;
329
        }
330
    }
331
    cnt = 0; f1 = 0; f2 = 0;
332
    c->stride_size = 2;
333
    c2.stride_size = 2;
334
    pcurr = p1;
335
    if (pkt.size > 0) {
336
        memcpy(p, pkt.data, pkt.size);
337
        c->frame[0] = p;
338
        c->frame_len[0] = pkt.size;
339
        f1++;
340
        p += pkt.size;
341
    }
342
    while (1) {
343
        res = av_read_frame(s, &pkt);
344
        if (res >= 0) {
345
            st = s->streams[pkt.stream_index];
346
            if (pkt.flags & PKT_FLAG_KEY) {
347
                cnt++;
348
                if (cnt == 2) {
349
                    return f1;
350
                }
351
            }
352
            memcpy(pcurr, pkt.data, pkt.size);
353
            if (pcurr == p) {
354
                c->frame[f1] = pcurr;
355
                c->frame_len[f1] = pkt.size;
356
                p += pkt.size;
357
                pcurr = p1;
358
                f1++;
359
            } else {
360
                c2.frame[f2] = pcurr;
361
                c2.frame_len[f2] = pkt.size;
362
                p1 += pkt.size;
363
                pcurr = p;
364
                f2++;
365
            }
366
        } else {
367
            pkt.size = 0;
368

369
            return f1;
370
        }
371
    }
372

373
    return 0;
374
}
375
#endif
376

    
377
struct chunkiser_iface in_avf = {
378
  .open = avf_open,
379
  .close = avf_close,
380
  .chunkise = avf_chunkise,
381
};