[FFmpeg-devel] [PATCH 3/4] avformat/pp_bnk: treat music files are stereo
Zane van Iperen
zane at zanevaniperen.com
Tue Mar 16 08:22:53 EET 2021
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 | 60 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 50 insertions(+), 10 deletions(-)
diff --git a/libavformat/pp_bnk.c b/libavformat/pp_bnk.c
index 8364de1fd9..970ef09923 100644
--- a/libavformat/pp_bnk.c
+++ b/libavformat/pp_bnk.c
@@ -55,6 +55,8 @@ typedef struct PPBnkCtx {
int track_count;
PPBnkCtxTrack *tracks;
uint32_t current_track;
+ int is_music;
+ AVPacket pkt;
} PPBnkCtx;
enum {
@@ -194,8 +196,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 +210,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 +266,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(&ctx->pkt, size);
+ else if (ctx->current_track == 0)
+ ret = av_new_packet(&ctx->pkt, size * 2);
+ else
+ ret = 0;
+
+ if (ret < 0)
+ return ret;
+
+ if (ctx->is_music)
+ ret = avio_read(s->pb, ctx->pkt.data + size * ctx->current_track, size);
+ else
+ ret = avio_read(s->pb, ctx->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;
@@ -261,10 +289,21 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt)
return ret;
}
- trk->bytes_read += ret;
- pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
- pkt->stream_index = ctx->current_track++;
- pkt->duration = ret * 2;
+ trk->bytes_read += ret;
+ ctx->pkt.flags &= ~AV_PKT_FLAG_CORRUPT;
+ ctx->pkt.stream_index = ctx->current_track++;
+ ctx->pkt.duration = ret * 2;
+
+ if (ctx->is_music) {
+ if (ctx->pkt.stream_index == 0)
+ return FFERROR_REDO;
+
+ ctx->pkt.stream_index = 0;
+ } else {
+ ctx->pkt.size = ret;
+ }
+
+ av_packet_move_ref(pkt, &ctx->pkt);
return 0;
}
@@ -277,6 +316,7 @@ static int pp_bnk_read_close(AVFormatContext *s)
PPBnkCtx *ctx = s->priv_data;
av_freep(&ctx->tracks);
+ av_packet_unref(&ctx->pkt);
return 0;
}
--
2.29.3
More information about the ffmpeg-devel
mailing list