Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 69ae8acb

History | View | Annotate | Download (10.3 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 "../input-stream.h"
12
#include "../payload.h"
13
#include "../input.h"                //TODO: for flags. Check if we can do something smarter
14

    
15
#define STATIC_BUFF_SIZE 1000 * 1024
16
#define HEADER_REFRESH_PERIOD 50
17

    
18
struct input_stream {
19
  AVFormatContext *s;
20
  bool loop;        //loop on input file infinitely
21
  int audio_stream;
22
  int video_stream;
23
  int64_t last_ts;
24
  int64_t base_ts;
25
  int frames_since_global_headers;
26
};
27

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

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

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

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

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

    
111
struct input_stream *input_stream_open(const char *fname, int *period, uint16_t flags)
112
{
113
  struct input_stream *desc;
114
  int i, res;
115

    
116
  avcodec_register_all();
117
  av_register_all();
118

    
119
  desc = malloc(sizeof(struct input_stream));
120
  if (desc == NULL) {
121
    return NULL;
122
  }
123
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
124
  if (res < 0) {
125
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
126

    
127
    return NULL;
128
  }
129

    
130
  res = av_find_stream_info(desc->s);
131
  if (res < 0) {
132
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
133

    
134
    return NULL;
135
  }
136
  desc->video_stream = -1;
137
  desc->audio_stream = -1;
138
  desc->last_ts = 0;
139
  desc->base_ts = 0;
140
  desc->frames_since_global_headers = 0;
141
  desc->loop = flags & INPUT_LOOP;
142
  for (i = 0; i < desc->s->nb_streams; i++) {
143
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
144
      desc->video_stream = i;
145
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
146
              desc->s->streams[i]->r_frame_rate.num,
147
              desc->s->streams[i]->r_frame_rate.den,
148
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
149
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
150
    }
151
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
152
      desc->audio_stream = i;
153
    }
154
  }
155

    
156
  dump_format(desc->s, 0, fname, 0);
157

    
158
  return desc;
159
}
160

    
161
void input_stream_close(struct input_stream *s)
162
{
163
    av_close_input_file(s->s);
164
    free(s);
165
}
166

    
167
int input_stream_rewind(struct input_stream *s)
168
{
169
    int ret;
170

    
171
    ret = av_seek_frame(s->s,-1,0,0);
172
    s->base_ts = s->last_ts;
173

    
174
    return ret;
175
}
176

    
177

    
178
#if 0
179
int input_get_1(struct input_stream *s, struct chunk *c)
180
{
181
    static AVPacket pkt;
182
    static int inited;
183
    AVStream *st;
184
    int res;
185
    static uint8_t static_buff[STATIC_BUFF_SIZE];
186
    static int cid;
187
    uint8_t *p;
188

189
    p = static_buff;
190
    if (inited == 0) {
191
        inited = 1;
192
        res = av_read_frame(s->s, &pkt);
193
        if (res < 0) {
194
            fprintf(stderr, "First read failed: %d!!!\n", res);
195

196
            return 0;
197
        }
198
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
199
            fprintf(stderr, "First frame is not key frame!!!\n");
200

201
            return 0;
202
        }
203
    }
204
    c->timestamp = pkt.dts;
205
    memcpy(p, pkt.data, pkt.size);
206
    p += pkt.size;
207
    while (1) {
208
        res = av_read_frame(s->s, &pkt);
209
        if (res >= 0) {
210
            st = s->s->streams[pkt.stream_index];
211
            if (pkt.flags & PKT_FLAG_KEY) {
212
                c->size = p - static_buff;
213
                c->data = malloc(c->size);
214
                if (c->data == NULL) {
215
                  return 0;
216
                }
217
                memcpy(c->data, static_buff, c->size);
218
                c->attributes_size = 0;
219
                c->attributes = NULL;
220
                c->id = cid++; 
221
                return 1;
222
            }
223
            memcpy(p, pkt.data, pkt.size);
224
            p += pkt.size;
225
        } else {
226
            if (p - static_buff > 0) {
227
                c->size = p - static_buff;
228
                c->data = malloc(c->size);
229
                if (c->data == NULL) {
230
                  return 0;
231
                }
232
                memcpy(c->data, static_buff, c->size);
233
                c->attributes_size = 0;
234
                c->attributes = NULL;
235
                c->id = cid++; 
236
                return 1;
237
            }
238
            return 0;
239
        }
240
    }
241

242
    return 0;
243
}
244
#endif
245

    
246
uint8_t *chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
247
{
248
    AVPacket pkt;
249
    int res;
250
    uint8_t *data;
251
    int header_out, header_size;
252

    
253
    res = av_read_frame(s->s, &pkt);
254
    if (res < 0) {
255
      if (s->loop) {
256
        if (input_stream_rewind(s) >= 0) {
257
          *size = 0;
258
          *ts = s->last_ts;
259

    
260
          return NULL;
261
        }
262
      }
263
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
264
      *size = -1;
265

    
266
      return NULL;
267
    }
268
    if (pkt.stream_index != s->video_stream) {
269
      *size = 0;
270
      *ts = s->last_ts;
271
      av_free_packet(&pkt);
272

    
273
      return NULL;
274
    }
275

    
276
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
277
      header_size = VIDEO_PAYLOAD_HEADER_SIZE;
278
    }
279
    header_out = (pkt.flags & PKT_FLAG_KEY) != 0;
280
    if (header_out == 0) {
281
      s->frames_since_global_headers++;
282
      if (s->frames_since_global_headers == HEADER_REFRESH_PERIOD) {
283
        s->frames_since_global_headers = 0;
284
        header_out = 1;
285
      }
286
    }
287
    *size = pkt.size + s->s->streams[pkt.stream_index]->codec->extradata_size * header_out + header_size + FRAME_HEADER_SIZE;
288
    data = malloc(*size);
289
    if (data == NULL) {
290
      *size = -1;
291
      av_free_packet(&pkt);
292

    
293
      return NULL;
294
    }
295
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
296
      video_header_fill(data, s->s->streams[pkt.stream_index]);
297
    }
298
    data[VIDEO_PAYLOAD_HEADER_SIZE - 1] = 1;
299
    frame_header_fill(data + VIDEO_PAYLOAD_HEADER_SIZE, *size - header_size - FRAME_HEADER_SIZE, &pkt, s->s->streams[pkt.stream_index], s->base_ts);
300

    
301
    if (header_out && s->s->streams[pkt.stream_index]->codec->extradata_size) {
302
      memcpy(data + header_size + FRAME_HEADER_SIZE, s->s->streams[pkt.stream_index]->codec->extradata, s->s->streams[pkt.stream_index]->codec->extradata_size);
303
      memcpy(data + header_size + FRAME_HEADER_SIZE + s->s->streams[pkt.stream_index]->codec->extradata_size, pkt.data, pkt.size);
304
    } else {
305
      memcpy(data + header_size + FRAME_HEADER_SIZE, pkt.data, pkt.size);
306
    }
307
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
308
    dprintf("pkt.dts=%ld TS1=%lu" , pkt.dts, *ts);
309
    *ts += s->base_ts;
310
    dprintf(" TS2=%lu\n",*ts);
311
    s->last_ts = *ts;
312
    av_free_packet(&pkt);
313

    
314
    return data;
315
}
316

    
317
#if 0
318
int chunk_read_avs1(void *s_h, struct chunk *c)
319
{
320
    AVFormatContext *s = s_h;
321
    static AVPacket pkt;
322
    static int inited;
323
    AVStream *st;
324
    int res;
325
    int cnt;
326
    static uint8_t static_buff[STATIC_BUFF_SIZE];
327
    uint8_t *p, *pcurr;
328
    static uint8_t *p1;
329
    static struct chunk c2;
330
    int f1;
331
    static int f2;
332

333
    if (p1) {
334
        c2.id = c->id;
335
        *c = c2;
336
        p1 = NULL;
337

338
        return f2;
339
    }
340

341
    p = static_buff;
342
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
343
    if (inited == 0) {
344
        inited = 1;
345
        res = av_read_frame(s, &pkt);
346
        if (res < 0) {
347
            fprintf(stderr, "First read failed: %d!!!\n", res);
348

349
            return 0;
350
        }
351
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
352
            fprintf(stderr, "First frame is not key frame!!!\n");
353

354
            return 0;
355
        }
356
    }
357
    cnt = 0; f1 = 0; f2 = 0;
358
    c->stride_size = 2;
359
    c2.stride_size = 2;
360
    pcurr = p1;
361
    if (pkt.size > 0) {
362
        memcpy(p, pkt.data, pkt.size);
363
        c->frame[0] = p;
364
        c->frame_len[0] = pkt.size;
365
        f1++;
366
        p += pkt.size;
367
    }
368
    while (1) {
369
        res = av_read_frame(s, &pkt);
370
        if (res >= 0) {
371
            st = s->streams[pkt.stream_index];
372
            if (pkt.flags & PKT_FLAG_KEY) {
373
                cnt++;
374
                if (cnt == 2) {
375
                    return f1;
376
                }
377
            }
378
            memcpy(pcurr, pkt.data, pkt.size);
379
            if (pcurr == p) {
380
                c->frame[f1] = pcurr;
381
                c->frame_len[f1] = pkt.size;
382
                p += pkt.size;
383
                pcurr = p1;
384
                f1++;
385
            } else {
386
                c2.frame[f2] = pcurr;
387
                c2.frame_len[f2] = pkt.size;
388
                p1 += pkt.size;
389
                pcurr = p;
390
                f2++;
391
            }
392
        } else {
393
            pkt.size = 0;
394

395
            return f1;
396
        }
397
    }
398

399
    return 0;
400
}
401
#endif