Lynne: > This allows to (re)mux Sony ATRAC1 files. > > Patch attached > > +#include "libavutil/intreadwrite.h" > +#include "avformat.h" > +#include "rawenc.h" > + > +#define AT1_SU_SIZE 212 > + > +typedef struct AEAEncContext { > + uint32_t frame_cnt; > +} AEAEncContext; > + > +static int aea_write_header(AVFormatContext *s) > +{ > + AVDictionaryEntry *dtmp; > + AVCodecParameters *par = s->streams[0]->codecpar; > + AVIOContext *pb = s->pb; > + > + if (par->channels != 1 && par->channels != 2) { > + av_log(s, AV_LOG_ERROR, "Unsupported number of channels %i!\n", > par->channels); > + return AVERROR(EINVAL); > + } > + > + if (par->sample_rate != 44100) { > + av_log(s, AV_LOG_ERROR, "Unsupported samplerate %i!\n", > par->sample_rate); > + return AVERROR(EINVAL); > + } > + > + if (par->block_align != (AT1_SU_SIZE * par->channels)) { > + av_log(s, AV_LOG_ERROR, "Unsupported block align %i!\n", > par->block_align); > + return AVERROR(EINVAL); > + } > + > + avio_wl32(pb, 0x800); // magic > + > + dtmp = av_dict_get(s->metadata, "title", NULL, 0); > + if (dtmp) { > + int len = FFMIN(strlen(dtmp->value), 15); > + avio_write(pb, dtmp->value, len); > + for (int i = 0; i < (16 - len); i++) > + avio_w8(pb, 0); > + } else { > + avio_wl64(pb, 0); > + avio_wl64(pb, 0); > + }
How about int len = 0; ... if (dtmp) { len = FFMIN avio_write(pb, drmp->value, len); } ffio_fill(pb, 0, 16 - len); > + > + avio_skip(pb, 240); // not needed > + skip? For a muxer? There is a danger of producing nondeterministic output here. Better add these 240 bytes to the ffio_fill I just suggested. > + avio_wl32(pb, 0); // #frames field overwritten when closing This could also be done by ffio_fill. > + avio_w8 (pb, par->channels); // Number of channels > + > + /* Skip to 2048 */ > + avio_skip(pb, 2048 - avio_tell(pb)); Same problem as above. Best to just use ffio_fill(pb, 0, 2048 - 265). > + > + return 0; > +} > + > +static int aea_write_packet(AVFormatContext *s, AVPacket *pkt) > +{ > + AEAEncContext *ctx = s->priv_data; > + ctx->frame_cnt++; Unnecessary: The muxing code generically sets AVStream.nb_frames. You can just use ff_raw_write_packet as your write_packet function and can remove the whole context. > + return ff_raw_write_packet(s, pkt); > +} > + > +static int aea_write_trailer(AVFormatContext *s) > +{ > + AVIOContext *pb = s->pb; > + AEAEncContext *ctx = s->priv_data; > + > + if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && ctx->frame_cnt > 1) { > + int64_t end = avio_tell(pb); > + > + avio_seek(pb, 260, SEEK_SET); > + avio_wl32(pb, ctx->frame_cnt); > + avio_seek(pb, end, SEEK_SET); > + } > + > + return 0; > +} > + > +AVOutputFormat ff_aea_muxer = { > + .name = "aea", > + .long_name = NULL_IF_CONFIG_SMALL("MD STUDIO audio"), > + .priv_data_size = sizeof(AEAEncContext), > + .extensions = "aea", > + .audio_codec = AV_CODEC_ID_ATRAC1, > + .write_header = aea_write_header, > + .write_packet = aea_write_packet, > + .write_trailer = aea_write_trailer, > + .flags = AVFMT_NOTIMESTAMPS, > +}; _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".