Esempio n. 1
0
int64_t swr_next_pts(struct SwrContext *s, int64_t pts){
    if(pts == INT64_MIN)
        return s->outpts;

    if (s->firstpts == AV_NOPTS_VALUE)
        s->outpts = s->firstpts = pts;

    if(s->min_compensation >= FLT_MAX) {
        return (s->outpts = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate));
    } else {
        int64_t delta = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate) - s->outpts + s->drop_output*(int64_t)s->in_sample_rate;
        double fdelta = delta /(double)(s->in_sample_rate * (int64_t)s->out_sample_rate);

        if(fabs(fdelta) > s->min_compensation) {
            if(s->outpts == s->firstpts || fabs(fdelta) > s->min_hard_compensation){
                int ret;
                if(delta > 0) ret = swr_inject_silence(s,  delta / s->out_sample_rate);
                else          ret = swr_drop_output   (s, -delta / s-> in_sample_rate);
                if(ret<0){
                    av_log(s, AV_LOG_ERROR, "Failed to compensate for timestamp delta of %f\n", fdelta);
                }
            } else if(s->soft_compensation_duration && s->max_soft_compensation) {
                int duration = s->out_sample_rate * s->soft_compensation_duration;
                double max_soft_compensation = s->max_soft_compensation / (s->max_soft_compensation < 0 ? -s->in_sample_rate : 1);
                int comp = av_clipf(fdelta, -max_soft_compensation, max_soft_compensation) * duration ;
                av_log(s, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n", fdelta, comp, duration);
                swr_set_compensation(s, comp, duration);
            }
        }

        return s->outpts;
    }
}
Esempio n. 2
0
static int audio_decode_frame(VideoState *is, double *pts_ptr)
{
    int len1, len2, decoded_data_size;
    AVPacket *pkt = &is->audio_pkt;
    int got_frame = 0;
    int64_t dec_channel_layout;
    int wanted_nb_samples, resampled_data_size, n;

    double pts;

    for (;;) {

        while (is->audio_pkt_size > 0) {

            if (is->isPause == true) //判断暂停
            {
                SDL_Delay(10);
                continue;
            }

            if (!is->audio_frame) {
                if (!(is->audio_frame = av_frame_alloc())) {
                    return AVERROR(ENOMEM);
                }
            } else
            {
//                avcodec_get_frame_default(is->audio_frame);
                memset(is->audio_frame, 0, sizeof(AVFrame));
                av_frame_unref(is->audio_frame);
            }

            len1 = avcodec_decode_audio4(is->audio_st->codec, is->audio_frame,
                    &got_frame, pkt);
            if (len1 < 0) {
                // error, skip the frame
                is->audio_pkt_size = 0;
                break;
            }

            is->audio_pkt_data += len1;
            is->audio_pkt_size -= len1;

            if (!got_frame)
                continue;

            /* 计算解码出来的桢需要的缓冲大小 */
            decoded_data_size = av_samples_get_buffer_size(NULL,
                    is->audio_frame->channels, is->audio_frame->nb_samples,
                    (AVSampleFormat)is->audio_frame->format, 1);

            dec_channel_layout =
                    (is->audio_frame->channel_layout
                            && is->audio_frame->channels
                                    == av_get_channel_layout_nb_channels(
                                            is->audio_frame->channel_layout)) ?
                            is->audio_frame->channel_layout :
                            av_get_default_channel_layout(
                                    is->audio_frame->channels);

            wanted_nb_samples = is->audio_frame->nb_samples;

            if (is->audio_frame->format != is->audio_src_fmt
                    || dec_channel_layout != is->audio_src_channel_layout
                    || is->audio_frame->sample_rate != is->audio_src_freq
                    || (wanted_nb_samples != is->audio_frame->nb_samples
                            && !is->swr_ctx)) {
                if (is->swr_ctx)
                    swr_free(&is->swr_ctx);
                is->swr_ctx = swr_alloc_set_opts(NULL,
                        is->audio_tgt_channel_layout, (AVSampleFormat)is->audio_tgt_fmt,
                        is->audio_tgt_freq, dec_channel_layout,
                        (AVSampleFormat)is->audio_frame->format, is->audio_frame->sample_rate,
                        0, NULL);
                if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
                    //fprintf(stderr,"swr_init() failed\n");
                    break;
                }
                is->audio_src_channel_layout = dec_channel_layout;
                is->audio_src_channels = is->audio_st->codec->channels;
                is->audio_src_freq = is->audio_st->codec->sample_rate;
                is->audio_src_fmt = is->audio_st->codec->sample_fmt;
            }

            /* 这里我们可以对采样数进行调整,增加或者减少,一般可以用来做声画同步 */
            if (is->swr_ctx) {
                const uint8_t **in =
                        (const uint8_t **) is->audio_frame->extended_data;
                uint8_t *out[] = { is->audio_buf2 };
                if (wanted_nb_samples != is->audio_frame->nb_samples) {
                    if (swr_set_compensation(is->swr_ctx,
                            (wanted_nb_samples - is->audio_frame->nb_samples)
                                    * is->audio_tgt_freq
                                    / is->audio_frame->sample_rate,
                            wanted_nb_samples * is->audio_tgt_freq
                                    / is->audio_frame->sample_rate) < 0) {
                        //fprintf(stderr,"swr_set_compensation() failed\n");
                        break;
                    }
                }

                len2 = swr_convert(is->swr_ctx, out,
                        sizeof(is->audio_buf2) / is->audio_tgt_channels
                                / av_get_bytes_per_sample(is->audio_tgt_fmt),
                        in, is->audio_frame->nb_samples);
                if (len2 < 0) {
                    //fprintf(stderr,"swr_convert() failed\n");
                    break;
                }
                if (len2
                        == sizeof(is->audio_buf2) / is->audio_tgt_channels
                                / av_get_bytes_per_sample(is->audio_tgt_fmt)) {
                    //fprintf(stderr,"warning: audio buffer is probably too small\n");
                    swr_init(is->swr_ctx);
                }
                is->audio_buf = is->audio_buf2;
                resampled_data_size = len2 * is->audio_tgt_channels
                        * av_get_bytes_per_sample(is->audio_tgt_fmt);
            } else {
                resampled_data_size = decoded_data_size;
                is->audio_buf = is->audio_frame->data[0];
            }

            pts = is->audio_clock;
            *pts_ptr = pts;
            n = 2 * is->audio_st->codec->channels;
            is->audio_clock += (double) resampled_data_size
                    / (double) (n * is->audio_st->codec->sample_rate);


            if (is->seek_flag_audio)
            {
                //发生了跳转 则跳过关键帧到目的时间的这几帧
               if (is->audio_clock < is->seek_time)
               {
                   break;
               }
               else
               {
                   is->seek_flag_audio = 0;
               }
            }


            // We have data, return it and come back for more later
            return resampled_data_size;
        }

        if (pkt->data)
            av_free_packet(pkt);
        memset(pkt, 0, sizeof(*pkt));

        if (is->quit)
            return -1;

        if (is->isPause == true) //判断暂停
        {
            SDL_Delay(10);
            continue;
        }

        if (packet_queue_get(&is->audioq, pkt, 0) <= 0)
        {
            return -1;
        }

        //收到这个数据 说明刚刚执行过跳转 现在需要把解码器的数据 清除一下
        if(strcmp((char*)pkt->data,FLUSH_DATA) == 0)
        {
            avcodec_flush_buffers(is->audio_st->codec);
            av_free_packet(pkt);
            continue;
        }

        is->audio_pkt_data = pkt->data;
        is->audio_pkt_size = pkt->size;

        /* if update, update the audio clock w/pts */
        if (pkt->pts != AV_NOPTS_VALUE) {
            is->audio_clock = av_q2d(is->audio_st->time_base) * pkt->pts;
        }
    }

    return 0;
}
Esempio n. 3
0
int audio_decode_frame(FFmpegState *st) {
	int len1, len2, decoded_data_size;
	AVPacket *pkt = &st->audio_pkt;
	int got_frame = 0;
	int64_t dec_channel_layout;
	int wanted_nb_samples, resampled_data_size;

	for (;;) {
		while (st->audio_pkt_size > 0) {
			if (!st->aFrame) {
				if (!(st->aFrame = av_frame_alloc())) {
					return AVERROR(ENOMEM);
				}
			}
			//else
			//    avcodec_get_frame_defaults(st->aFrame);

			len1 = avcodec_decode_audio4(st->audio_st->codec, st->aFrame, &got_frame, pkt);
			if (len1 < 0) {
				// error, skip the frame
				st->audio_pkt_size = 0;
				break;
			}

			st->audio_pkt_data += len1;
			st->audio_pkt_size -= len1;

			if (!got_frame)
				continue;

			decoded_data_size = av_samples_get_buffer_size(NULL,
				st->aFrame->channels,
				st->aFrame->nb_samples,
				(AVSampleFormat)st->aFrame->format, 1);

			dec_channel_layout = (st->aFrame->channel_layout && st->aFrame->channels
				== av_get_channel_layout_nb_channels(st->aFrame->channel_layout))
				? st->aFrame->channel_layout
				: av_get_default_channel_layout(st->aFrame->channels);

			wanted_nb_samples = st->aFrame->nb_samples;

			//fprintf(stderr, "wanted_nb_samples = %d\n", wanted_nb_samples);
			if (st->swr) {
				// const uint8_t *in[] = { is->audio_frame->data[0] };
				const uint8_t **in = (const uint8_t **)st->aFrame->extended_data;
				uint8_t *out[] = { st->audio_buf2 };
				if (wanted_nb_samples != st->aFrame->nb_samples) {
					if (swr_set_compensation(st->swr, (wanted_nb_samples - st->aFrame->nb_samples)
						* st->audio_tgt_freq / st->aFrame->sample_rate,
						wanted_nb_samples * st->audio_tgt_freq / st->aFrame->sample_rate) < 0) {
						fprintf(stderr, "swr_set_compensation() failed\n");
						break;
					}
				}

				// SWR Convert
				len2 = swr_convert(st->swr, out,
					sizeof(st->audio_buf2)
					/ st->audio_tgt_channels
					/ av_get_bytes_per_sample(st->audio_tgt_fmt),
					in, st->aFrame->nb_samples);
				if (len2 < 0) {
					fprintf(stderr, "swr_convert() failed\n");
					break;
				}

				if (len2 == sizeof(st->audio_buf2) / st->audio_tgt_channels / av_get_bytes_per_sample(st->audio_tgt_fmt)) {
					fprintf(stderr, "warning: audio buffer is probably too small\n");
					swr_init(st->swr);
				}

				st->audio_buf = st->audio_buf2;
				resampled_data_size = len2 * st->audio_tgt_channels * av_get_bytes_per_sample(st->audio_tgt_fmt);
			}
			else {
				resampled_data_size = decoded_data_size;
				st->audio_buf = st->aFrame->data[0];
			}

			// Update the wave buffer
			if (st->wave) {
				update_wave_buffer(st->audio_buf, resampled_data_size);
			}

			// We have data, return it and come back for more later
			return resampled_data_size;
		}

		// Read packet from queue
		if (pkt->data) av_free_packet(pkt);
		memset(pkt, 0, sizeof(*pkt));
		if (st->quit) return -1;
		if (packet_queue_get(&st->audioq, pkt, 1) < 0) return -1;

		st->audio_pkt_data = pkt->data;
		st->audio_pkt_size = pkt->size;
	}
}