import{assert as h,toDataView as f}from"../misc.js";import{Muxer as d}from"../muxer.js";import{getXingOffset as l,INFO as g,readFrameHeader as c,XING as w}from"../../shared/mp3-misc.js";import{Mp3Writer as p}from"./mp3-writer.js";export class Mp3Muxer extends d{constructor(s,e){super(s),this.xingFrameData=null,this.frameCount=0,this.framePositions=[],this.format=e,this.writer=s._writer,this.mp3Writer=new p(s._writer)}async start(){}async getMimeType(){return"audio/mpeg"}async addEncodedVideoPacket(){throw new Error("MP3 does not support video.")}async addEncodedAudioPacket(s,e){const a=await this.mutex.acquire();try{const r=this.format._options.xingHeader!==!1;if(!this.xingFrameData&&r){const i=f(e.data);if(i.byteLength<4)throw new Error("Invalid MP3 header in sample.");const n=i.getUint32(0,!1),t=c(n,{pos:0,fileSize:null});if(!t)throw new Error("Invalid MP3 header in sample.");const o=l(t.mpegVersionId,t.channel);if(i.byteLength>=o+4){const m=i.getUint32(o,!1);if(m===w||m===g)return}this.xingFrameData={mpegVersionId:t.mpegVersionId,layer:t.layer,frequencyIndex:t.frequencyIndex,channel:t.channel,modeExtension:t.modeExtension,copyright:t.copyright,original:t.original,emphasis:t.emphasis,frameCount:null,fileSize:null,toc:null},this.mp3Writer.writeXingFrame(this.xingFrameData),this.frameCount++}this.validateAndNormalizeTimestamp(s,e.timestamp,e.type==="key"),this.writer.write(e.data),this.frameCount++,await this.writer.flush(),r&&this.framePositions.push(this.writer.getPos())}finally{a()}}async addSubtitleCue(){throw new Error("MP3 does not support subtitles.")}async finalize(){if(!this.xingFrameData)return;const s=await this.mutex.acquire(),e=this.writer.getPos();this.writer.seek(0);const a=new Uint8Array(100);for(let r=0;r<100;r++){const i=Math.floor(this.framePositions.length*(r/100));h(i!==-1&&i<this.framePositions.length);const n=this.framePositions[i];a[r]=256*(n/e)}if(this.xingFrameData.frameCount=this.frameCount,this.xingFrameData.fileSize=e,this.xingFrameData.toc=a,this.format._options.onXingFrame&&this.writer.startTrackingWrites(),this.mp3Writer.writeXingFrame(this.xingFrameData),this.format._options.onXingFrame){const{data:r,start:i}=this.writer.stopTrackingWrites();this.format._options.onXingFrame(r,i)}this.writer.seek(e),s()}}
