[Libav-user] Issue with decoding APE files

Michał Kurowski mkurowski at n7mobile.com
Fri Aug 7 12:42:33 CEST 2015


Hi,

	I'm developing a mobile music player and I'm planning to use ffmpeg for some of the audio decoding. The decoder has been written some time ago, but it seems to work ok (music plays without issues). Except for APE files. The result is as if the decoder was seeking ~0.8 second forward after reading each packet, so that a 4 minute track plays in a couple of seconds. Decoding of one stereo 96kHz APE file results in frames with 18432 bytes of data each (4608 samples, or 48 ms), but the consecutive timestamps are as follows:
49.152000
49.919998
50.688000
51.456001
52.223999
I've created an ugly workaround by manually counting the total number of samples read and seeking to the correct time just after decoding a packet. The music sounds ok on APE files (but has occassional glitches on ALAC M4As- which is unnacceptable, in addition to the overall ugliness of the solution). I've downloaded a windows build of the library and converted the APE files to MP3s using CLI ffmpeg. Files converted just fine, so they are not broken and I assume it is not a bug of ffmpeg itself. My android code is built against ffmpeg 2.7.2, the same version that I've downloaded pre-built for Windows.
Excerpts from my code (with some logging and non-ffmpeg related stuff removed for readibility):

//OPENING THE FILE

     ret = avformat_open_input(&(af->mFormatCtx), native_name, NULL, NULL);
     if (ret < 0)
     {
         return 0;
     }

     ret = avformat_find_stream_info(af->mFormatCtx, NULL);
     if (ret < 0)
     {
         return 0;
     }
     ret = av_find_best_stream(af->mFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &(af->mCodec), 0);
     if (ret < 0) {
         return 0;
     }
     af->mAudioStream = ret;
     af->mCodecCtx = af->mFormatCtx->streams[af->mAudioStream]->codec;
     af->mDuration = -1.0f;
     af->mDTimebase = av_q2d(af->mFormatCtx->streams[af->mAudioStream]->time_base);
     double duration = (double)af->mFormatCtx->streams[af->mAudioStream]->duration;
     if (af->mDTimebase > 0.0 && duration > 0.0)
     {
     	af->mDuration = (float)(duration*af->mDTimebase);
     }

     av_opt_set_int(af->mCodecCtx, "refcounted_frames", 1, 0);

     if ((ret = avcodec_open2(af->mCodecCtx, af->mCodec, NULL)) < 0)
     {
         return 0;
     }

//READING A FRAME

     int got_frame;
     int ret;

	for (;;)
	{
		ret = av_read_frame(af->mFormatCtx, &(af->mPacket));
		if (ret < 0)
		{
			return ret;
		}

	    if (af->mPacket.stream_index == af->mAudioStream)
	    {
	            avcodec_get_frame_defaults(frame);
	            got_frame = 0;
	            ret = avcodec_decode_audio4(af->mCodecCtx, frame, &got_frame, &(af->mPacket));
	            if (ret < 0)
	            {
	                continue;
	            }

	            if (got_frame)
	            {
	            	af->mTimestamp = (float)(af->mPacket.pts * af->mDTimebase);
	            	return 0;
	            }
	    }
	     av_free_packet(&(af->mPacket));
	}

What am I doing wrong? Should I pass some additional parameters to the codec?

Best regards,

	Michał Kurowski


More information about the Libav-user mailing list