[FFmpeg-devel] [PATCH v2] avformat/pp_bnk: treat music files are stereo
Andreas Rheinhardt
andreas.rheinhardt at gmail.com
Tue Mar 16 10:40:23 EET 2021
Zane van Iperen:
> These files are technically a series of planar mono tracks.
> If the "music" flag is set, merge the packets from the two
> mono tracks, essentially replicating:
>
> [0:a:0][0:a:1]join=inputs=2:channel_layout=stereo[a]
>
> Signed-off-by: Zane van Iperen <zane at zanevaniperen.com>
> ---
> libavformat/pp_bnk.c | 51 ++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 45 insertions(+), 6 deletions(-)
>
> diff --git a/libavformat/pp_bnk.c b/libavformat/pp_bnk.c
> index 8364de1fd9..eba53a01a3 100644
> --- a/libavformat/pp_bnk.c
> +++ b/libavformat/pp_bnk.c
> @@ -55,6 +55,7 @@ typedef struct PPBnkCtx {
> int track_count;
> PPBnkCtxTrack *tracks;
> uint32_t current_track;
> + int is_music;
> } PPBnkCtx;
>
> enum {
> @@ -194,8 +195,12 @@ static int pp_bnk_read_header(AVFormatContext *s)
> goto fail;
> }
>
> + ctx->is_music = (hdr.flags & PP_BNK_FLAG_MUSIC) &&
> + (ctx->track_count == 2) &&
> + (ctx->tracks[0].data_size == ctx->tracks[1].data_size);
> +
> /* Build the streams. */
> - for (int i = 0; i < ctx->track_count; i++) {
> + for (int i = 0; i < (ctx->is_music ? 1 : ctx->track_count); i++) {
> if (!(st = avformat_new_stream(s, NULL))) {
> ret = AVERROR(ENOMEM);
> goto fail;
> @@ -204,14 +209,21 @@ static int pp_bnk_read_header(AVFormatContext *s)
> par = st->codecpar;
> par->codec_type = AVMEDIA_TYPE_AUDIO;
> par->codec_id = AV_CODEC_ID_ADPCM_IMA_CUNNING;
> - par->format = AV_SAMPLE_FMT_S16;
> - par->channel_layout = AV_CH_LAYOUT_MONO;
> - par->channels = 1;
> + par->format = AV_SAMPLE_FMT_S16P;
> +
> + if (ctx->is_music) {
> + par->channel_layout = AV_CH_LAYOUT_STEREO;
> + par->channels = 2;
> + } else {
> + par->channel_layout = AV_CH_LAYOUT_MONO;
> + par->channels = 1;
> + }
> +
> par->sample_rate = hdr.sample_rate;
> par->bits_per_coded_sample = 4;
> par->bits_per_raw_sample = 16;
> par->block_align = 1;
> - par->bit_rate = par->sample_rate * par->bits_per_coded_sample;
> + par->bit_rate = par->sample_rate * par->bits_per_coded_sample * par->channels;
>
> avpriv_set_pts_info(st, 64, 1, par->sample_rate);
> st->start_time = 0;
> @@ -253,7 +265,22 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt)
>
> size = FFMIN(trk->data_size - trk->bytes_read, PP_BNK_MAX_READ_SIZE);
>
> - if ((ret = av_get_packet(s->pb, pkt, size)) == AVERROR_EOF) {
> + if (!ctx->is_music)
> + ret = av_new_packet(pkt, size);
> + else if (ctx->current_track == 0)
> + ret = av_new_packet(pkt, size * 2);
> + else
> + ret = 0;
> +
> + if (ret < 0)
> + return ret;
> +
> + if (ctx->is_music)
> + ret = avio_read(s->pb, pkt->data + size * ctx->current_track, size);
> + else
> + ret = avio_read(s->pb, pkt->data, size);
> +
> + if (ret == AVERROR_EOF) {
> /* If we've hit EOF, don't attempt this track again. */
> trk->data_size = trk->bytes_read;
> continue;
> @@ -265,6 +292,18 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt)
> pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
> pkt->stream_index = ctx->current_track++;
> pkt->duration = ret * 2;
> +
> + if (ctx->is_music) {
> + if (pkt->stream_index == 0) {
> + ctx->current_track--;
I have to admit to be confused by this. Won't this imply that
ctx->current_track will always be zero for music files until you hit the
bytes_read == data_size check and that you just overwrite and therefore
leak the already allocated packets?
> + continue;
> + }
> +
> + pkt->stream_index = 0;
> + } else {
> + pkt->size = ret;
> + }
> +
> return 0;
> }
>
>
More information about the ffmpeg-devel
mailing list