Statistics
| Branch: | Revision:

streamers / Chunkiser / input-stream-avs.c @ 46c24e94

History | View | Annotate | Download (7.51 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 "../input-stream.h"
11
#include "../input.h"                //TODO: for flags. Check if we can do something smarter
12
#define STATIC_BUFF_SIZE 1000 * 1024
13
#define HEADER_REFRESH_PERIOD 50
14

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

    
25
struct input_stream *input_stream_open(const char *fname, int *period, uint16_t flags)
26
{
27
  struct input_stream *desc;
28
  int i, res;
29

    
30
  avcodec_register_all();
31
  av_register_all();
32

    
33
  desc = malloc(sizeof(struct input_stream));
34
  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
  desc->last_ts = 0;
53
  desc->base_ts = 0;
54
  desc->frames_since_global_headers = 0;
55
  desc->loop = flags & INPUT_LOOP;
56
  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
      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
      *period = av_rescale(1000000, desc->s->streams[i]->r_frame_rate.den, desc->s->streams[i]->r_frame_rate.num);
64
    }
65
    if (desc->audio_stream == -1 && desc->s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
66
      desc->audio_stream = i;
67
    }
68
  }
69

    
70
  dump_format(desc->s, 0, fname, 0);
71

    
72
  return desc;
73
}
74

    
75
void input_stream_close(struct input_stream *s)
76
{
77
    av_close_input_file(s->s);
78
    free(s);
79
}
80

    
81
int input_stream_rewind(struct input_stream *s)
82
{
83
    int ret;
84

    
85
    ret = av_seek_frame(s->s,-1,0,0);
86
    s->base_ts = s->last_ts;
87

    
88
    return ret;
89
}
90

    
91

    
92
#if 0
93
int input_get_1(struct input_stream *s, struct chunk *c)
94
{
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
        res = av_read_frame(s->s, &pkt);
107
        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
        res = av_read_frame(s->s, &pkt);
123
        if (res >= 0) {
124
            st = s->s->streams[pkt.stream_index];
125
            if (pkt.flags & PKT_FLAG_KEY) {
126
                c->size = p - static_buff;
127
                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
                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
                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
                c->id = cid++; 
150
                return 1;
151
            }
152
            return 0;
153
        }
154
    }
155

156
    return 0;
157
}
158
#endif
159

    
160
uint8_t *chunkise(struct input_stream *s, int id, int *size, uint64_t *ts)
161
{
162
    AVPacket pkt;
163
    int res;
164
    uint8_t *data;
165
    int header_out;
166

    
167
    res = av_read_frame(s->s, &pkt);
168
    if (res < 0) {
169
      if (s->loop) {
170
        if (input_stream_rewind(s) >= 0) {
171
          *size = 0;
172
          *ts = s->last_ts;
173

    
174
          return NULL;
175
        }
176
      }
177
      fprintf(stderr, "AVPacket read failed: %d!!!\n", res);
178
      *size = -1;
179

    
180
      return NULL;
181
    }
182
    if (pkt.stream_index != s->video_stream) {
183
      *size = 0;
184
      *ts = s->last_ts;
185
      av_free_packet(&pkt);
186

    
187
      return NULL;
188
    }
189
    header_out = (pkt.flags & PKT_FLAG_KEY) != 0;
190
    if (header_out == 0) {
191
      s->frames_since_global_headers++;
192
      if (s->frames_since_global_headers == HEADER_REFRESH_PERIOD) {
193
        s->frames_since_global_headers = 0;
194
        header_out = 1;
195
      }
196
    }
197
    *size = pkt.size + s->s->streams[pkt.stream_index]->codec->extradata_size * header_out;
198
    data = malloc(*size);
199
    if (data == NULL) {
200
      *size = -1;
201
      av_free_packet(&pkt);
202

    
203
      return NULL;
204
    }
205
    if (header_out && s->s->streams[pkt.stream_index]->codec->extradata_size) {
206
      memcpy(data, s->s->streams[pkt.stream_index]->codec->extradata, s->s->streams[pkt.stream_index]->codec->extradata_size);
207
      memcpy(data + s->s->streams[pkt.stream_index]->codec->extradata_size, pkt.data, pkt.size);
208
    } else {
209
      memcpy(data, pkt.data, pkt.size);
210
    }
211
    *ts = av_rescale_q(pkt.dts, s->s->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
212
    *ts += s->base_ts;
213
    s->last_ts = *ts;
214
    av_free_packet(&pkt);
215

    
216
    return data;
217
}
218

    
219
#if 0
220
int chunk_read_avs1(void *s_h, struct chunk *c)
221
{
222
    AVFormatContext *s = s_h;
223
    static AVPacket pkt;
224
    static int inited;
225
    AVStream *st;
226
    int res;
227
    int cnt;
228
    static uint8_t static_buff[STATIC_BUFF_SIZE];
229
    uint8_t *p, *pcurr;
230
    static uint8_t *p1;
231
    static struct chunk c2;
232
    int f1;
233
    static int f2;
234

235
    if (p1) {
236
        c2.id = c->id;
237
        *c = c2;
238
        p1 = NULL;
239

240
        return f2;
241
    }
242

243
    p = static_buff;
244
    p1 = static_buff + STATIC_BUFF_SIZE / 2;
245
    if (inited == 0) {
246
        inited = 1;
247
        res = av_read_frame(s, &pkt);
248
        if (res < 0) {
249
            fprintf(stderr, "First read failed: %d!!!\n", res);
250

251
            return 0;
252
        }
253
        if ((pkt.flags & PKT_FLAG_KEY) == 0) {
254
            fprintf(stderr, "First frame is not key frame!!!\n");
255

256
            return 0;
257
        }
258
    }
259
    cnt = 0; f1 = 0; f2 = 0;
260
    c->stride_size = 2;
261
    c2.stride_size = 2;
262
    pcurr = p1;
263
    if (pkt.size > 0) {
264
        memcpy(p, pkt.data, pkt.size);
265
        c->frame[0] = p;
266
        c->frame_len[0] = pkt.size;
267
        f1++;
268
        p += pkt.size;
269
    }
270
    while (1) {
271
        res = av_read_frame(s, &pkt);
272
        if (res >= 0) {
273
            st = s->streams[pkt.stream_index];
274
            if (pkt.flags & PKT_FLAG_KEY) {
275
                cnt++;
276
                if (cnt == 2) {
277
                    return f1;
278
                }
279
            }
280
            memcpy(pcurr, pkt.data, pkt.size);
281
            if (pcurr == p) {
282
                c->frame[f1] = pcurr;
283
                c->frame_len[f1] = pkt.size;
284
                p += pkt.size;
285
                pcurr = p1;
286
                f1++;
287
            } else {
288
                c2.frame[f2] = pcurr;
289
                c2.frame_len[f2] = pkt.size;
290
                p1 += pkt.size;
291
                pcurr = p;
292
                f2++;
293
            }
294
        } else {
295
            pkt.size = 0;
296

297
            return f1;
298
        }
299
    }
300

301
    return 0;
302
}
303
#endif