diff --git a/daemon/media_player.c b/daemon/media_player.c index fa19d3a8a..17097ede1 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -52,6 +52,21 @@ static unsigned int send_timer_flush(struct send_timer *st, void *ptr) { } +static void media_player_coder_shutdown(struct media_player_coder *c) { + avformat_close_input(&c->fmtctx); + codec_handler_free(&c->handler); + if (c->avioctx) { + if (c->avioctx->buffer) + av_freep(&c->avioctx->buffer); + av_freep(&c->avioctx); + } + c->avstream = NULL; + if (c->blob) + free(c->blob); + c->blob = NULL; + c->read_pos = STR_NULL; +} + // called with call->master lock in W static void media_player_shutdown(struct media_player *mp) { if (!mp) @@ -60,7 +75,6 @@ static void media_player_shutdown(struct media_player *mp) { //ilog(LOG_DEBUG, "shutting down media_player"); timerthread_obj_deschedule(&mp->tt_obj); mp->next_run.tv_sec = 0; - avformat_close_input(&mp->coder.fmtctx); if (mp->sink) { unsigned int num = send_timer_flush(mp->sink->send_timer, mp->coder.handler); @@ -70,17 +84,7 @@ static void media_player_shutdown(struct media_player *mp) { } mp->media = NULL; - codec_handler_free(&mp->coder.handler); - if (mp->coder.avioctx) { - if (mp->coder.avioctx->buffer) - av_freep(&mp->coder.avioctx->buffer); - av_freep(&mp->coder.avioctx); - } - mp->coder.avstream = NULL; - if (mp->coder.blob) - free(mp->coder.blob); - mp->coder.blob = NULL; - mp->coder.read_pos = STR_NULL; + media_player_coder_shutdown(&mp->coder); } #endif @@ -284,6 +288,38 @@ void send_timer_push(struct send_timer *st, struct codec_packet *cp) { #ifdef WITH_TRANSCODING +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 26, 0) +#define CODECPAR codecpar +#else +#define CODECPAR codec +#endif + + +static void media_player_coder_add_packet(struct media_player_coder *c, + void (*fn)(void *p, char *buf, size_t len, + long long us_dur, unsigned long long pts), void *p) { + // scale pts and duration according to sample rate + + long long duration_scaled = c->pkt->duration * c->avstream->CODECPAR->sample_rate + * c->avstream->time_base.num / c->avstream->time_base.den; + unsigned long long pts_scaled = c->pkt->pts * c->avstream->CODECPAR->sample_rate + * c->avstream->time_base.num / c->avstream->time_base.den; + + long long us_dur = c->pkt->duration * 1000000LL * c->avstream->time_base.num + / c->avstream->time_base.den; + ilog(LOG_DEBUG, "read media packet: pts %llu duration %lli (scaled %llu/%lli, %lli us), " + "sample rate %i, time_base %i/%i", + (unsigned long long) c->pkt->pts, + (long long) c->pkt->duration, + pts_scaled, + duration_scaled, + us_dur, + c->avstream->CODECPAR->sample_rate, + c->avstream->time_base.num, c->avstream->time_base.den); + + fn(p, (char *) c->pkt->data, c->pkt->size, us_dur, pts_scaled); +} + // find suitable output payload type static struct rtp_payload_type *media_player_get_dst_pt(struct media_player *mp) { @@ -336,12 +372,6 @@ int media_player_setup(struct media_player *mp, const struct rtp_payload_type *s return 0; } -#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 26, 0) -#define CODECPAR codecpar -#else -#define CODECPAR codec -#endif - static int __ensure_codec_handler(struct media_player *mp, const struct rtp_payload_type *dst_pt) { if (mp->coder.handler) return 0; @@ -452,26 +482,7 @@ static void media_player_read_packet(struct media_player *mp) { mp->last_frame_ts = mp->coder.pkt->pts; - // scale pts and duration according to sample rate - - long long duration_scaled = mp->coder.pkt->duration * mp->coder.avstream->CODECPAR->sample_rate - * mp->coder.avstream->time_base.num / mp->coder.avstream->time_base.den; - unsigned long long pts_scaled = mp->coder.pkt->pts * mp->coder.avstream->CODECPAR->sample_rate - * mp->coder.avstream->time_base.num / mp->coder.avstream->time_base.den; - - long long us_dur = mp->coder.pkt->duration * 1000000LL * mp->coder.avstream->time_base.num - / mp->coder.avstream->time_base.den; - ilog(LOG_DEBUG, "read media packet: pts %llu duration %lli (scaled %llu/%lli, %lli us), " - "sample rate %i, time_base %i/%i", - (unsigned long long) mp->coder.pkt->pts, - (long long) mp->coder.pkt->duration, - pts_scaled, - duration_scaled, - us_dur, - mp->coder.avstream->CODECPAR->sample_rate, - mp->coder.avstream->time_base.num, mp->coder.avstream->time_base.den); - - media_player_add_packet(mp, (char *) mp->coder.pkt->data, mp->coder.pkt->size, us_dur, pts_scaled); + media_player_coder_add_packet(&mp->coder, (void *) media_player_add_packet, mp); av_packet_unref(mp->coder.pkt); } @@ -573,19 +584,19 @@ int media_player_play_file(struct media_player *mp, const str *file, long long r #ifdef WITH_TRANSCODING static int __mp_avio_read_wrap(void *opaque, uint8_t *buf, int buf_size) { - struct media_player *mp = opaque; + struct media_player_coder *c = opaque; if (buf_size < 0) return AVERROR(EINVAL); if (buf_size == 0) return 0; - if (!mp->coder.read_pos.len) + if (!c->read_pos.len) return AVERROR_EOF; int len = buf_size; - if (len > mp->coder.read_pos.len) - len = mp->coder.read_pos.len; - memcpy(buf, mp->coder.read_pos.s, len); - str_shift(&mp->coder.read_pos, len); + if (len > c->read_pos.len) + len = c->read_pos.len; + memcpy(buf, c->read_pos.s, len); + str_shift(&c->read_pos, len); return len; } static int __mp_avio_read(void *opaque, uint8_t *buf, int buf_size) { @@ -594,24 +605,24 @@ static int __mp_avio_read(void *opaque, uint8_t *buf, int buf_size) { ilog(LOG_DEBUG, "__mp_avio_read(%i) = %i", buf_size, ret); return ret; } -static int64_t __mp_avio_seek_set(struct media_player *mp, int64_t offset) { +static int64_t __mp_avio_seek_set(struct media_player_coder *c, int64_t offset) { ilog(LOG_DEBUG, "__mp_avio_seek_set(%" PRIi64 ")", offset); if (offset < 0) return AVERROR(EINVAL); - mp->coder.read_pos = *mp->coder.blob; - if (str_shift(&mp->coder.read_pos, offset)) + c->read_pos = *c->blob; + if (str_shift(&c->read_pos, offset)) return AVERROR_EOF; return offset; } static int64_t __mp_avio_seek(void *opaque, int64_t offset, int whence) { ilog(LOG_DEBUG, "__mp_avio_seek(%" PRIi64 ", %i)", offset, whence); - struct media_player *mp = opaque; + struct media_player_coder *c = opaque; if (whence == SEEK_SET) - return __mp_avio_seek_set(mp, offset); + return __mp_avio_seek_set(c, offset); if (whence == SEEK_CUR) - return __mp_avio_seek_set(mp, ((int64_t) (mp->coder.read_pos.s - mp->coder.blob->s)) + offset); + return __mp_avio_seek_set(c, ((int64_t) (c->read_pos.s - c->blob->s)) + offset); if (whence == SEEK_END) - return __mp_avio_seek_set(mp, ((int64_t) mp->coder.blob->len) + offset); + return __mp_avio_seek_set(c, ((int64_t) c->blob->len) + offset); return AVERROR(EINVAL); } #endif @@ -644,7 +655,7 @@ int media_player_play_blob(struct media_player *mp, const str *blob, long long r if (!avio_buf) goto err; - mp->coder.avioctx = avio_alloc_context(avio_buf, DEFAULT_AVIO_BUFSIZE, 0, mp, __mp_avio_read, + mp->coder.avioctx = avio_alloc_context(avio_buf, DEFAULT_AVIO_BUFSIZE, 0, &mp->coder, __mp_avio_read, NULL, __mp_avio_seek); err = "failed to allocate AVIOContext"; if (!mp->coder.avioctx)