Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 74ff12bb

History | View | Annotate | Download (8.84 KB)

1 709f774c Luca
/*
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 30a6e902 Csaba Kiraly
#include <stdbool.h>
9 709f774c Luca
10 69b16605 Luca Abeni
#include "../input-stream.h"
11 30a6e902 Csaba Kiraly
#include "../input.h"                //TODO: for flags. Check if we can do something smarter
12 709f774c Luca
#define STATIC_BUFF_SIZE 1000 * 1024
13 01059d06 Luca Abeni
#define HEADER_REFRESH_PERIOD 50
14 709f774c Luca
15 afabfeb9 Luca Abeni
struct input_stream {
16 f9a86917 Luca Abeni
  AVFormatContext *s;
17 30a6e902 Csaba Kiraly
  bool loop;        //loop on input file infinitely
18 f9a86917 Luca Abeni
  int audio_stream;
19
  int video_stream;
20 bb1f75db Luca Abeni
  int64_t last_ts;
21 bd38fe7d Csaba Kiraly
  int64_t base_ts;
22 9c45209f Luca Abeni
  int frames_since_global_headers;
23 f9a86917 Luca Abeni
};
24
25 30a6e902 Csaba Kiraly
struct input_stream *input_stream_open(const char *fname, int *period, uint16_t flags)
26 709f774c Luca
{
27 afabfeb9 Luca Abeni
  struct input_stream *desc;
28 f9a86917 Luca Abeni
  int i, res;
29 709f774c Luca
30
  avcodec_register_all();
31
  av_register_all();
32
33 afabfeb9 Luca Abeni
  desc = malloc(sizeof(struct input_stream));
34 f9a86917 Luca Abeni
  if (desc == NULL) {
35
    return NULL;
36
  }
37
  res = av_open_input_file(&desc->s, fname, NULL, 0, NULL);
38
  if (res < 0) {
39
    fprintf(stderr, "Error opening %s: %d\n", fname, res);
40
41
    return NULL;
42
  }
43
44
  res = av_find_stream_info(desc->s);
45
  if (res < 0) {
46
    fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
47
48
    return NULL;
49
  }
50
  desc->video_stream = -1;
51
  desc->audio_stream = -1;
52 bb1f75db Luca Abeni
  desc->last_ts = 0;
53 bd38fe7d Csaba Kiraly
  desc->base_ts = 0;
54 9c45209f Luca Abeni
  desc->frames_since_global_headers = 0;
55 30a6e902 Csaba Kiraly
  desc->loop = flags & INPUT_LOOP;
56 f9a86917 Luca Abeni
  for (i = 0; i < desc->s->nb_streams; i++) {
57
    if (desc->video_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
58
      desc->video_stream = i;
59 62e428da Luca Abeni
      fprintf(stderr, "Video Frame Rate = %d/%d --- Period: %lld\n",
60
              desc->s->streams[i]->r_frame_rate.num,
61
              desc->s->streams[i]->r_frame_rate.den,
62
              av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num));
63 afabfeb9 Luca Abeni
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
64 709f774c Luca
    }
65 f9a86917 Luca Abeni
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
66
      desc->audio_stream = i;
67 709f774c Luca
    }
68 f9a86917 Luca Abeni
  }
69 709f774c Luca
70 f9a86917 Luca Abeni
  dump_format(desc->s, 0, fname, 0);
71 709f774c Luca
72 f9a86917 Luca Abeni
  return desc;
73 709f774c Luca
}
74
75 afabfeb9 Luca Abeni
void input_stream_close(struct input_stream *s)
76 709f774c Luca
{
77 f9a86917 Luca Abeni
    av_close_input_file(s->s);
78
    free(s);
79 709f774c Luca
}
80
81 52976315 Csaba Kiraly
int input_stream_rewind(struct input_stream *s)
82 bd38fe7d Csaba Kiraly
{
83 52976315 Csaba Kiraly
    int ret;
84
85
    ret = av_seek_frame(s->s,-1,0,0);
86 bd38fe7d Csaba Kiraly
    s->base_ts = s->last_ts;
87 52976315 Csaba Kiraly
88
    return ret;
89 bd38fe7d Csaba Kiraly
}
90
91
92 69b16605 Luca Abeni
#if 0
93 afabfeb9 Luca Abeni
int input_get_1(struct input_stream *s, struct chunk *c)
94 709f774c Luca
{
95
    static AVPacket pkt;
96
    static int inited;
97
    AVStream *st;
98
    int res;
99
    static uint8_t static_buff[STATIC_BUFF_SIZE];
100
    static int cid;
101
    uint8_t *p;
102

103
    p = static_buff;
104
    if (inited == 0) {
105
        inited = 1;
106 f9a86917 Luca Abeni
        res = av_read_frame(s->s, &pkt);
107 709f774c Luca
        if (res < 0) {
108
            fprintf(stderr, "First read failed: %d!!!\n", res);
109

110
            return 0;
111
        }
112
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
113
            fprintf(stderr, "First frame is not key frame!!!\n");
114

115
            return 0;
116
        }
117
    }
118
    c->timestamp = pkt.dts;
119
    memcpy(p, pkt.data, pkt.size);
120
    p += pkt.size;
121
    while (1) {
122 f9a86917 Luca Abeni
        res = av_read_frame(s->s, &pkt);
123 709f774c Luca
        if (res >= 0) {
124 f9a86917 Luca Abeni
            st = s->s->streams[pkt.stream_index];
125 709f774c Luca
            if (pkt.flags & PKT_FLAG_KEY) {
126
                c->size = p - static_buff;
127 4bb789ed Luca
                c->data = malloc(c->size);
128
                if (c->data == NULL) {
129
                  return 0;
130
                }
131
                memcpy(c->data, static_buff, c->size);
132
                c->attributes_size = 0;
133
                c->attributes = NULL;
134 709f774c Luca
                c->id = cid++; 
135
                return 1;
136
            }
137
            memcpy(p, pkt.data, pkt.size);
138
            p += pkt.size;
139
        } else {
140
            if (p - static_buff > 0) {
141
                c->size = p - static_buff;
142 4bb789ed Luca
                c->data = malloc(c->size);
143
                if (c->data == NULL) {
144
                  return 0;
145
                }
146
                memcpy(c->data, static_buff, c->size);
147
                c->attributes_size = 0;
148
                c->attributes = NULL;
149 709f774c Luca
                c->id = cid++; 
150
                return 1;
151
            }
152
            return 0;
153
        }
154
    }
155

156
    return 0;
157
}
158 69b16605 Luca Abeni
#endif
159 709f774c Luca
160 afabfeb9 Luca Abeni
uint8_t *chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
161 4a18aab5 Luca
{
162
    AVPacket pkt;
163
    int res;
164 afabfeb9 Luca Abeni
    uint8_t *data;
165 3ee4345d Luca Abeni
    int header_out, header_size;
166 4a18aab5 Luca
167 f9a86917 Luca Abeni
    res = av_read_frame(s->s, &pkt);
168 4a18aab5 Luca
    if (res < 0) {
169 30a6e902 Csaba Kiraly
      if (s->loop) {
170
        if (input_stream_rewind(s) >= 0) {
171
          *size = 0;
172
          *ts = s->last_ts;
173 52976315 Csaba Kiraly
174 30a6e902 Csaba Kiraly
          return NULL;
175
        }
176 52976315 Csaba Kiraly
      }
177 30a6e902 Csaba Kiraly
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
178
      *size = -1;
179 f9a86917 Luca Abeni
180 afabfeb9 Luca Abeni
      return NULL;
181 f9a86917 Luca Abeni
    }
182
    if (pkt.stream_index != s->video_stream) {
183 afabfeb9 Luca Abeni
      *size = 0;
184 bb1f75db Luca Abeni
      *ts = s->last_ts;
185 a0e704c7 Luca Abeni
      av_free_packet(&pkt);
186 4a18aab5 Luca
187 afabfeb9 Luca Abeni
      return NULL;
188 4a18aab5 Luca
    }
189 3ee4345d Luca Abeni
190
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
191 74ff12bb Luca Abeni
      header_size = 1 + 2 + 2 + 2 + 2 + 1; // 1 Frame type + 2 width + 2 height + 2 frame rate num + 2 frame rate den + 1 number of frames
192 3ee4345d Luca Abeni
    }
193 01059d06 Luca Abeni
    header_out = (pkt.flags & PKT_FLAG_KEY) != 0;
194 9c45209f Luca Abeni
    if (header_out == 0) {
195
      s->frames_since_global_headers++;
196
      if (s->frames_since_global_headers == HEADER_REFRESH_PERIOD) {
197
        s->frames_since_global_headers = 0;
198
        header_out = 1;
199
      }
200
    }
201 74ff12bb Luca Abeni
    *size = pkt.size + s->s->streams[pkt.stream_index]->codec->extradata_size * header_out + header_size + 2;
202 bb1f75db Luca Abeni
    data = malloc(*size);
203 afabfeb9 Luca Abeni
    if (data == NULL) {
204
      *size = -1;
205 a0e704c7 Luca Abeni
      av_free_packet(&pkt);
206 afabfeb9 Luca Abeni
207
      return NULL;
208 4a18aab5 Luca
    }
209 3ee4345d Luca Abeni
    if (s->s->streams[pkt.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
210 74ff12bb Luca Abeni
      int num, den;
211
212 3ee4345d Luca Abeni
      data[0] = 1;
213
      data[1] = s->s->streams[pkt.stream_index]->codec->width >> 8;
214
      data[2] = s->s->streams[pkt.stream_index]->codec->width & 0xFF;
215
      data[3] = s->s->streams[pkt.stream_index]->codec->height >> 8;
216
      data[4] = s->s->streams[pkt.stream_index]->codec->height & 0xFF;
217 74ff12bb Luca Abeni
      num = s->s->streams[pkt.stream_index]->avg_frame_rate.num;
218
      den = s->s->streams[pkt.stream_index]->avg_frame_rate.den;
219
//fprintf(stderr, "Rate: %d/%d\n", num, den);
220
      if (num == 0) {
221
        num = s->s->streams[pkt.stream_index]->r_frame_rate.num;
222
        den = s->s->streams[pkt.stream_index]->r_frame_rate.den;
223
      }
224
      if (num > (1 << 16)) {
225
        num /= 1000;
226
        den /= 1000;
227
      }
228
      data[5] = num >> 8;
229
      data[6] = num & 0xFF;
230
      data[7] = den >> 8;
231
      data[8] = den & 0xFF;
232
      data[9] = 1;
233
      data[10] = (*size - header_size - 2) >> 8;
234
      data[11] = (*size - header_size - 2) & 0xFF;
235 3ee4345d Luca Abeni
    }
236 01059d06 Luca Abeni
    if (header_out && s->s->streams[pkt.stream_index]->codec->extradata_size) {
237 74ff12bb Luca Abeni
      memcpy(data + header_size + 2, s->s->streams[pkt.stream_index]->codec->extradata, s->s->streams[pkt.stream_index]->codec->extradata_size);
238
      memcpy(data + header_size + 2 + s->s->streams[pkt.stream_index]->codec->extradata_size, pkt.data, pkt.size);
239 bb1f75db Luca Abeni
    } else {
240 74ff12bb Luca Abeni
      memcpy(data + header_size + 2, pkt.data, pkt.size);
241 bb1f75db Luca Abeni
    }
242 0aaea2fb Luca Abeni
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
243 bd38fe7d Csaba Kiraly
    *ts += s->base_ts;
244 bb1f75db Luca Abeni
    s->last_ts = *ts;
245 a0e704c7 Luca Abeni
    av_free_packet(&pkt);
246 afabfeb9 Luca Abeni
247
    return data;
248 4a18aab5 Luca
}
249
250 709f774c Luca
#if 0
251
int chunk_read_avs1(void *s_h, struct chunk *c)
252
{
253
    AVFormatContext *s = s_h;
254
    static AVPacket pkt;
255
    static int inited;
256
    AVStream *st;
257
    int res;
258
    int cnt;
259
    static uint8_t static_buff[STATIC_BUFF_SIZE];
260
    uint8_t *p, *pcurr;
261
    static uint8_t *p1;
262
    static struct chunk c2;
263
    int f1;
264
    static int f2;
265

266
    if (p1) {
267
        c2.id = c->id;
268
        *c = c2;
269
        p1 = NULL;
270

271
        return f2;
272
    }
273

274
    p = static_buff;
275
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
276
    if (inited == 0) {
277
        inited = 1;
278
        res = av_read_frame(s, &pkt);
279
        if (res < 0) {
280
            fprintf(stderr, "First read failed: %d!!!\n", res);
281

282
            return 0;
283
        }
284
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
285
            fprintf(stderr, "First frame is not key frame!!!\n");
286

287
            return 0;
288
        }
289
    }
290
    cnt = 0; f1 = 0; f2 = 0;
291
    c->stride_size = 2;
292
    c2.stride_size = 2;
293
    pcurr = p1;
294
    if (pkt.size > 0) {
295
        memcpy(p, pkt.data, pkt.size);
296
        c->frame[0] = p;
297
        c->frame_len[0] = pkt.size;
298
        f1++;
299
        p += pkt.size;
300
    }
301
    while (1) {
302
        res = av_read_frame(s, &pkt);
303
        if (res >= 0) {
304
            st = s->streams[pkt.stream_index];
305
            if (pkt.flags & PKT_FLAG_KEY) {
306
                cnt++;
307
                if (cnt == 2) {
308
                    return f1;
309
                }
310
            }
311
            memcpy(pcurr, pkt.data, pkt.size);
312
            if (pcurr == p) {
313
                c->frame[f1] = pcurr;
314
                c->frame_len[f1] = pkt.size;
315
                p += pkt.size;
316
                pcurr = p1;
317
                f1++;
318
            } else {
319
                c2.frame[f2] = pcurr;
320
                c2.frame_len[f2] = pkt.size;
321
                p1 += pkt.size;
322
                pcurr = p;
323
                f2++;
324
            }
325
        } else {
326
            pkt.size = 0;
327

328
            return f1;
329
        }
330
    }
331

332
    return 0;
333
}
334
#endif