Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (9.26 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
  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 chunkiser_ctx *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 chunkiser_ctx *avf_open(const char *fname, int *period, const char *config)
123
{
124
  struct chunkiser_ctx *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 chunkiser_ctx));
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
  free(cfg_tags);
159
  for (i = 0; i < desc->s->nb_streams; i++) {
160
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
161
      desc->video_stream = i;
162
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
163
              desc->s->streams[i]->r_frame_rate.num,
164
              desc->s->streams[i]->r_frame_rate.den,
165
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
166
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
167
    }
168
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
169
      desc->audio_stream = i;
170
    }
171
    if (desc->s->streams[i]->codec->codec_id == CODEC_ID_MPEG4) {
172
      desc->bsf[i] = av_bitstream_filter_init("dump_extra");
173
    } else if (desc->s->streams[i]->codec->codec_id == CODEC_ID_H264) {
174
      desc->bsf[i] = av_bitstream_filter_init("h264_mp4toannexb");
175
    } else {
176
      desc->bsf[i] = NULL;
177
    }
178
  }
179

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

    
182
  return desc;
183
}
184

    
185
static void avf_close(struct chunkiser_ctx *s)
186
{
187
  int i;
188

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

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

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

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

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

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

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

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

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

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

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

    
276
    return data;
277
}
278

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

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

300
        return f2;
301
    }
302

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

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

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

357
            return f1;
358
        }
359
    }
360

361
    return 0;
362
}
363
#endif
364

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