Reviewed-by: "Reynaldo H. Verdejo Pinochet" <reynaldo@osg.samsung.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
... | ... |
@@ -235,7 +235,7 @@ static int rtp_new_av_stream(HTTPContext *c, |
235 | 235 |
/* utils */ |
236 | 236 |
static size_t htmlencode (const char *src, char **dest); |
237 | 237 |
static inline void cp_html_entity (char *buffer, const char *entity); |
238 |
-static inline int check_codec_match(AVStream *ccf, AVStream *ccs, int stream); |
|
238 |
+static inline int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream); |
|
239 | 239 |
|
240 | 240 |
static const char *my_program_name; |
241 | 241 |
|
... | ... |
@@ -254,6 +254,21 @@ static AVLFG random_state; |
254 | 254 |
|
255 | 255 |
static FILE *logfile = NULL; |
256 | 256 |
|
257 |
+static void unlayer_stream(AVStream *st, LayeredAVStream *lst) |
|
258 |
+{ |
|
259 |
+ avcodec_free_context(&st->codec); |
|
260 |
+ avcodec_parameters_free(&st->codecpar); |
|
261 |
+#define COPY(a) st->a = lst->a; |
|
262 |
+ COPY(index) |
|
263 |
+ COPY(id) |
|
264 |
+ COPY(codec) |
|
265 |
+ COPY(codecpar) |
|
266 |
+ COPY(time_base) |
|
267 |
+ COPY(pts_wrap_bits) |
|
268 |
+ COPY(sample_aspect_ratio) |
|
269 |
+ COPY(recommended_encoder_configuration) |
|
270 |
+} |
|
271 |
+ |
|
257 | 272 |
static inline void cp_html_entity (char *buffer, const char *entity) { |
258 | 273 |
if (!buffer || !entity) |
259 | 274 |
return; |
... | ... |
@@ -1864,7 +1879,7 @@ static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream) |
1864 | 1864 |
int i, stream_no; |
1865 | 1865 |
const char *type = "unknown"; |
1866 | 1866 |
char parameters[64]; |
1867 |
- AVStream *st; |
|
1867 |
+ LayeredAVStream *st; |
|
1868 | 1868 |
AVCodec *codec; |
1869 | 1869 |
|
1870 | 1870 |
stream_no = stream->nb_streams; |
... | ... |
@@ -1984,7 +1999,7 @@ static void compute_status(HTTPContext *c) |
1984 | 1984 |
const char *video_codec_name_extra = ""; |
1985 | 1985 |
|
1986 | 1986 |
for(i=0;i<stream->nb_streams;i++) { |
1987 |
- AVStream *st = stream->streams[i]; |
|
1987 |
+ LayeredAVStream *st = stream->streams[i]; |
|
1988 | 1988 |
AVCodec *codec = avcodec_find_encoder(st->codecpar->codec_id); |
1989 | 1989 |
|
1990 | 1990 |
switch(st->codecpar->codec_type) { |
... | ... |
@@ -2256,14 +2271,12 @@ static int http_prepare_data(HTTPContext *c) |
2256 | 2256 |
return AVERROR(ENOMEM); |
2257 | 2257 |
c->pfmt_ctx = ctx; |
2258 | 2258 |
av_dict_copy(&(c->pfmt_ctx->metadata), c->stream->metadata, 0); |
2259 |
- c->pfmt_ctx->streams = av_mallocz_array(c->stream->nb_streams, |
|
2260 |
- sizeof(AVStream *)); |
|
2261 |
- if (!c->pfmt_ctx->streams) |
|
2262 |
- return AVERROR(ENOMEM); |
|
2263 | 2259 |
|
2264 | 2260 |
for(i=0;i<c->stream->nb_streams;i++) { |
2265 |
- AVStream *src; |
|
2266 |
- c->pfmt_ctx->streams[i] = av_mallocz(sizeof(AVStream)); |
|
2261 |
+ LayeredAVStream *src; |
|
2262 |
+ AVStream *st = avformat_new_stream(c->pfmt_ctx, NULL); |
|
2263 |
+ if (!st) |
|
2264 |
+ return AVERROR(ENOMEM); |
|
2267 | 2265 |
|
2268 | 2266 |
/* if file or feed, then just take streams from FFServerStream |
2269 | 2267 |
* struct */ |
... | ... |
@@ -2273,14 +2286,14 @@ static int http_prepare_data(HTTPContext *c) |
2273 | 2273 |
else |
2274 | 2274 |
src = c->stream->feed->streams[c->stream->feed_streams[i]]; |
2275 | 2275 |
|
2276 |
- *(c->pfmt_ctx->streams[i]) = *src; |
|
2277 |
- c->pfmt_ctx->streams[i]->priv_data = 0; |
|
2276 |
+ unlayer_stream(c->pfmt_ctx->streams[i], src); //TODO we no longer copy st->internal, does this matter? |
|
2277 |
+ av_assert0(!c->pfmt_ctx->streams[i]->priv_data); |
|
2278 | 2278 |
/* XXX: should be done in AVStream, not in codec */ |
2279 | 2279 |
c->pfmt_ctx->streams[i]->codec->frame_number = 0; |
2280 | 2280 |
} |
2281 | 2281 |
/* set output format parameters */ |
2282 | 2282 |
c->pfmt_ctx->oformat = c->stream->fmt; |
2283 |
- c->pfmt_ctx->nb_streams = c->stream->nb_streams; |
|
2283 |
+ av_assert0(c->pfmt_ctx->nb_streams == c->stream->nb_streams); |
|
2284 | 2284 |
|
2285 | 2285 |
c->got_key_frame = 0; |
2286 | 2286 |
|
... | ... |
@@ -2807,7 +2820,7 @@ static int http_receive_data(HTTPContext *c) |
2807 | 2807 |
} |
2808 | 2808 |
|
2809 | 2809 |
for (i = 0; i < s->nb_streams; i++) { |
2810 |
- AVStream *fst = feed->streams[i]; |
|
2810 |
+ LayeredAVStream *fst = feed->streams[i]; |
|
2811 | 2811 |
AVStream *st = s->streams[i]; |
2812 | 2812 |
avcodec_copy_context(fst->codec, st->codec); |
2813 | 2813 |
} |
... | ... |
@@ -3424,19 +3437,16 @@ static int rtp_new_av_stream(HTTPContext *c, |
3424 | 3424 |
if (!st) |
3425 | 3425 |
goto fail; |
3426 | 3426 |
|
3427 |
- av_freep(&st->codec); |
|
3428 |
- av_freep(&st->info); |
|
3429 | 3427 |
st_internal = st->internal; |
3430 | 3428 |
|
3431 | 3429 |
if (!c->stream->feed || |
3432 | 3430 |
c->stream->feed == c->stream) |
3433 |
- memcpy(st, c->stream->streams[stream_index], sizeof(AVStream)); |
|
3431 |
+ unlayer_stream(st, c->stream->streams[stream_index]); |
|
3434 | 3432 |
else |
3435 |
- memcpy(st, |
|
3436 |
- c->stream->feed->streams[c->stream->feed_streams[stream_index]], |
|
3437 |
- sizeof(AVStream)); |
|
3438 |
- st->priv_data = NULL; |
|
3439 |
- st->internal = st_internal; |
|
3433 |
+ unlayer_stream(st, |
|
3434 |
+ c->stream->feed->streams[c->stream->feed_streams[stream_index]]); |
|
3435 |
+ av_assert0(st->priv_data == NULL); |
|
3436 |
+ av_assert0(st->internal == st_internal); |
|
3440 | 3437 |
|
3441 | 3438 |
/* build destination RTP address */ |
3442 | 3439 |
ipaddr = inet_ntoa(dest_addr->sin_addr); |
... | ... |
@@ -3504,15 +3514,15 @@ static int rtp_new_av_stream(HTTPContext *c, |
3504 | 3504 |
/* ffserver initialization */ |
3505 | 3505 |
|
3506 | 3506 |
/* FIXME: This code should use avformat_new_stream() */ |
3507 |
-static AVStream *add_av_stream1(FFServerStream *stream, |
|
3507 |
+static LayeredAVStream *add_av_stream1(FFServerStream *stream, |
|
3508 | 3508 |
AVCodecContext *codec, int copy) |
3509 | 3509 |
{ |
3510 |
- AVStream *fst; |
|
3510 |
+ LayeredAVStream *fst; |
|
3511 | 3511 |
|
3512 | 3512 |
if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams)) |
3513 | 3513 |
return NULL; |
3514 | 3514 |
|
3515 |
- fst = av_mallocz(sizeof(AVStream)); |
|
3515 |
+ fst = av_mallocz(sizeof(*fst)); |
|
3516 | 3516 |
if (!fst) |
3517 | 3517 |
return NULL; |
3518 | 3518 |
if (copy) { |
... | ... |
@@ -3528,20 +3538,20 @@ static AVStream *add_av_stream1(FFServerStream *stream, |
3528 | 3528 |
*/ |
3529 | 3529 |
fst->codec = codec; |
3530 | 3530 |
|
3531 |
- fst->internal = av_mallocz(sizeof(*fst->internal)); |
|
3532 |
- fst->internal->avctx = avcodec_alloc_context3(NULL); |
|
3531 |
+ //NOTE we previously allocated internal & internal->avctx, these seemed uneeded though |
|
3533 | 3532 |
fst->codecpar = avcodec_parameters_alloc(); |
3534 | 3533 |
fst->index = stream->nb_streams; |
3535 |
- avpriv_set_pts_info(fst, 33, 1, 90000); |
|
3534 |
+ fst->time_base = (AVRational) {1, 90000}; |
|
3535 |
+ fst->pts_wrap_bits = 33; |
|
3536 | 3536 |
fst->sample_aspect_ratio = codec->sample_aspect_ratio; |
3537 | 3537 |
stream->streams[stream->nb_streams++] = fst; |
3538 | 3538 |
return fst; |
3539 | 3539 |
} |
3540 | 3540 |
|
3541 | 3541 |
/* return the stream number in the feed */ |
3542 |
-static int add_av_stream(FFServerStream *feed, AVStream *st) |
|
3542 |
+static int add_av_stream(FFServerStream *feed, LayeredAVStream *st) |
|
3543 | 3543 |
{ |
3544 |
- AVStream *fst; |
|
3544 |
+ LayeredAVStream *fst; |
|
3545 | 3545 |
AVCodecContext *av, *av1; |
3546 | 3546 |
int i; |
3547 | 3547 |
|
... | ... |
@@ -3575,9 +3585,9 @@ static int add_av_stream(FFServerStream *feed, AVStream *st) |
3575 | 3575 |
fst = add_av_stream1(feed, av, 0); |
3576 | 3576 |
if (!fst) |
3577 | 3577 |
return -1; |
3578 |
- if (av_stream_get_recommended_encoder_configuration(st)) |
|
3579 |
- av_stream_set_recommended_encoder_configuration(fst, |
|
3580 |
- av_strdup(av_stream_get_recommended_encoder_configuration(st))); |
|
3578 |
+ if (st->recommended_encoder_configuration) |
|
3579 |
+ fst->recommended_encoder_configuration = |
|
3580 |
+ av_strdup(st->recommended_encoder_configuration); |
|
3581 | 3581 |
return feed->nb_streams - 1; |
3582 | 3582 |
} |
3583 | 3583 |
|
... | ... |
@@ -3653,7 +3663,7 @@ static void build_file_streams(void) |
3653 | 3653 |
} |
3654 | 3654 |
|
3655 | 3655 |
static inline |
3656 |
-int check_codec_match(AVStream *ccf, AVStream *ccs, int stream) |
|
3656 |
+int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream) |
|
3657 | 3657 |
{ |
3658 | 3658 |
int matches = 1; |
3659 | 3659 |
|
... | ... |
@@ -3741,7 +3751,8 @@ static int build_feed_streams(void) |
3741 | 3741 |
|
3742 | 3742 |
matches = 1; |
3743 | 3743 |
for(i=0;i<s->nb_streams;i++) { |
3744 |
- AVStream *sf, *ss; |
|
3744 |
+ AVStream *ss; |
|
3745 |
+ LayeredAVStream *sf; |
|
3745 | 3746 |
|
3746 | 3747 |
sf = feed->streams[i]; |
3747 | 3748 |
ss = s->streams[i]; |
... | ... |
@@ -3796,8 +3807,14 @@ drop: |
3796 | 3796 |
goto bail; |
3797 | 3797 |
} |
3798 | 3798 |
s->oformat = feed->fmt; |
3799 |
- s->nb_streams = feed->nb_streams; |
|
3800 |
- s->streams = feed->streams; |
|
3799 |
+ for (i = 0; i<feed->nb_streams; i++) { |
|
3800 |
+ AVStream *st = avformat_new_stream(s, NULL); // FIXME free this |
|
3801 |
+ if (!st) { |
|
3802 |
+ http_log("Failed to allocate stream\n"); |
|
3803 |
+ goto bail; |
|
3804 |
+ } |
|
3805 |
+ unlayer_stream(st, feed->streams[i]); |
|
3806 |
+ } |
|
3801 | 3807 |
if (avformat_write_header(s, NULL) < 0) { |
3802 | 3808 |
http_log("Container doesn't support the required parameters\n"); |
3803 | 3809 |
avio_closep(&s->pb); |
... | ... |
@@ -3847,7 +3864,7 @@ static void compute_bandwidth(void) |
3847 | 3847 |
for(stream = config.first_stream; stream; stream = stream->next) { |
3848 | 3848 |
bandwidth = 0; |
3849 | 3849 |
for(i=0;i<stream->nb_streams;i++) { |
3850 |
- AVStream *st = stream->streams[i]; |
|
3850 |
+ LayeredAVStream *st = stream->streams[i]; |
|
3851 | 3851 |
switch(st->codec->codec_type) { |
3852 | 3852 |
case AVMEDIA_TYPE_AUDIO: |
3853 | 3853 |
case AVMEDIA_TYPE_VIDEO: |
... | ... |
@@ -182,7 +182,7 @@ bail: |
182 | 182 |
static void add_codec(FFServerStream *stream, AVCodecContext *av, |
183 | 183 |
FFServerConfig *config) |
184 | 184 |
{ |
185 |
- AVStream *st; |
|
185 |
+ LayeredAVStream *st; |
|
186 | 186 |
AVDictionary **opts, *recommended = NULL; |
187 | 187 |
char *enc_config; |
188 | 188 |
|
... | ... |
@@ -313,12 +313,12 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, |
313 | 313 |
} |
314 | 314 |
|
315 | 315 |
done: |
316 |
- st = av_mallocz(sizeof(AVStream)); |
|
316 |
+ st = av_mallocz(sizeof(*st)); |
|
317 | 317 |
if (!st) |
318 | 318 |
return; |
319 | 319 |
av_dict_get_string(recommended, &enc_config, '=', ','); |
320 | 320 |
av_dict_free(&recommended); |
321 |
- av_stream_set_recommended_encoder_configuration(st, enc_config); |
|
321 |
+ st->recommended_encoder_configuration = enc_config; |
|
322 | 322 |
st->codec = av; |
323 | 323 |
stream->streams[stream->nb_streams++] = st; |
324 | 324 |
} |
... | ... |
@@ -49,6 +49,24 @@ typedef struct FFServerIPAddressACL { |
49 | 49 |
struct in_addr last; |
50 | 50 |
} FFServerIPAddressACL; |
51 | 51 |
|
52 |
+/** |
|
53 |
+ * This holds the stream parameters for an AVStream, it cannot be a AVStream |
|
54 |
+ * because AVStreams cannot be instanciated without a AVFormatContext, especially |
|
55 |
+ * not outside libavformat. |
|
56 |
+ * |
|
57 |
+ * The fields of this struct have the same semantics as the fields of an AVStream. |
|
58 |
+ */ |
|
59 |
+typedef struct LayeredAVStream { |
|
60 |
+ int index; |
|
61 |
+ int id; |
|
62 |
+ AVCodecParameters *codecpar; |
|
63 |
+ AVCodecContext *codec; |
|
64 |
+ AVRational time_base; |
|
65 |
+ int pts_wrap_bits; |
|
66 |
+ AVRational sample_aspect_ratio; |
|
67 |
+ char *recommended_encoder_configuration; |
|
68 |
+} LayeredAVStream; |
|
69 |
+ |
|
52 | 70 |
/* description of each stream of the ffserver.conf file */ |
53 | 71 |
typedef struct FFServerStream { |
54 | 72 |
enum FFServerStreamType stream_type; |
... | ... |
@@ -64,7 +82,7 @@ typedef struct FFServerStream { |
64 | 64 |
int prebuffer; /* Number of milliseconds early to start */ |
65 | 65 |
int64_t max_time; /* Number of milliseconds to run */ |
66 | 66 |
int send_on_key; |
67 |
- AVStream *streams[FFSERVER_MAX_STREAMS]; |
|
67 |
+ LayeredAVStream *streams[FFSERVER_MAX_STREAMS]; |
|
68 | 68 |
int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */ |
69 | 69 |
char feed_filename[1024]; /* file name of the feed storage, or |
70 | 70 |
input file name for a stream */ |