mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 12:36:41 +08:00 
			
		
		
		
	avformat/cafenc: derive Opus frame size from the relevant stream parameters
Use the stream duration as last resort, as an off-by-one result of the "st->duration / (caf->packets - 1)" calculation can break playback on some devices. Also, don't write the sample_rate value propagated by encoders like libopus. The sample rate of the audio fed to it is irrelevant after being encoded. Fixes ticket #9930. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
		| @@ -53,7 +53,11 @@ static uint32_t codec_flags(enum AVCodecID codec_id) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int block_align) { | static uint32_t samples_per_packet(const AVCodecParameters *par) { | ||||||
|  |     enum AVCodecID codec_id = par->codec_id; | ||||||
|  |     int channels = par->ch_layout.nb_channels, block_align = par->block_align; | ||||||
|  |     int frame_size = par->frame_size, sample_rate = par->sample_rate; | ||||||
|  |  | ||||||
|     switch (codec_id) { |     switch (codec_id) { | ||||||
|     case AV_CODEC_ID_PCM_S8: |     case AV_CODEC_ID_PCM_S8: | ||||||
|     case AV_CODEC_ID_PCM_S16LE: |     case AV_CODEC_ID_PCM_S16LE: | ||||||
| @@ -83,6 +87,8 @@ static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int bl | |||||||
|         return 320; |         return 320; | ||||||
|     case AV_CODEC_ID_MP1: |     case AV_CODEC_ID_MP1: | ||||||
|         return 384; |         return 384; | ||||||
|  |     case AV_CODEC_ID_OPUS: | ||||||
|  |         return frame_size * 48000 / sample_rate; | ||||||
|     case AV_CODEC_ID_MP2: |     case AV_CODEC_ID_MP2: | ||||||
|     case AV_CODEC_ID_MP3: |     case AV_CODEC_ID_MP3: | ||||||
|         return 1152; |         return 1152; | ||||||
| @@ -110,7 +116,7 @@ static int caf_write_header(AVFormatContext *s) | |||||||
|     AVDictionaryEntry *t = NULL; |     AVDictionaryEntry *t = NULL; | ||||||
|     unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, par->codec_id); |     unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, par->codec_id); | ||||||
|     int64_t chunk_size = 0; |     int64_t chunk_size = 0; | ||||||
|     int frame_size = par->frame_size; |     int frame_size = par->frame_size, sample_rate = par->sample_rate; | ||||||
|  |  | ||||||
|     if (s->nb_streams != 1) { |     if (s->nb_streams != 1) { | ||||||
|         av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n"); |         av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n"); | ||||||
| @@ -139,7 +145,10 @@ static int caf_write_header(AVFormatContext *s) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) |     if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) | ||||||
|         frame_size = samples_per_packet(par->codec_id, par->ch_layout.nb_channels, par->block_align); |         frame_size = samples_per_packet(par); | ||||||
|  |  | ||||||
|  |     if (par->codec_id == AV_CODEC_ID_OPUS) | ||||||
|  |         sample_rate = 48000; | ||||||
|  |  | ||||||
|     ffio_wfourcc(pb, "caff"); //< mFileType |     ffio_wfourcc(pb, "caff"); //< mFileType | ||||||
|     avio_wb16(pb, 1);         //< mFileVersion |     avio_wb16(pb, 1);         //< mFileVersion | ||||||
| @@ -147,7 +156,7 @@ static int caf_write_header(AVFormatContext *s) | |||||||
|  |  | ||||||
|     ffio_wfourcc(pb, "desc");                         //< Audio Description chunk |     ffio_wfourcc(pb, "desc");                         //< Audio Description chunk | ||||||
|     avio_wb64(pb, 32);                                //< mChunkSize |     avio_wb64(pb, 32);                                //< mChunkSize | ||||||
|     avio_wb64(pb, av_double2int(par->sample_rate));   //< mSampleRate |     avio_wb64(pb, av_double2int(sample_rate));        //< mSampleRate | ||||||
|     avio_wl32(pb, codec_tag);                         //< mFormatID |     avio_wl32(pb, codec_tag);                         //< mFormatID | ||||||
|     avio_wb32(pb, codec_flags(par->codec_id));        //< mFormatFlags |     avio_wb32(pb, codec_flags(par->codec_id));        //< mFormatFlags | ||||||
|     avio_wb32(pb, par->block_align);                  //< mBytesPerPacket |     avio_wb32(pb, par->block_align);                  //< mBytesPerPacket | ||||||
| @@ -248,7 +257,7 @@ static int caf_write_trailer(AVFormatContext *s) | |||||||
|         avio_seek(pb, caf->data, SEEK_SET); |         avio_seek(pb, caf->data, SEEK_SET); | ||||||
|         avio_wb64(pb, file_size - caf->data - 8); |         avio_wb64(pb, file_size - caf->data - 8); | ||||||
|         if (!par->block_align) { |         if (!par->block_align) { | ||||||
|             int packet_size = samples_per_packet(par->codec_id, par->ch_layout.nb_channels, par->block_align); |             int packet_size = samples_per_packet(par); | ||||||
|             if (!packet_size) { |             if (!packet_size) { | ||||||
|                 packet_size = st->duration / (caf->packets - 1); |                 packet_size = st->duration / (caf->packets - 1); | ||||||
|                 avio_seek(pb, FRAME_SIZE_OFFSET, SEEK_SET); |                 avio_seek(pb, FRAME_SIZE_OFFSET, SEEK_SET); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 James Almer
					James Almer