mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53:53 +00:00
Update to use avcodec_decode_audio4
This commit is contained in:
parent
27cd9ff732
commit
606fb982a8
2 changed files with 56 additions and 41 deletions
|
@ -165,6 +165,10 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder
|
|||
|
||||
VideoState *is;
|
||||
|
||||
AVFrame *mFrame;
|
||||
size_t mFramePos;
|
||||
size_t mFrameSize;
|
||||
|
||||
/* Add or subtract samples to get a better sync, return new
|
||||
* audio buffer size */
|
||||
int synchronize_audio(uint8_t *samples, int samples_size, double pts)
|
||||
|
@ -210,16 +214,19 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder
|
|||
{
|
||||
uint8_t *samples_end, *q;
|
||||
int nb;
|
||||
|
||||
/* add samples by copying final sample*/
|
||||
nb = (samples_size - wanted_size);
|
||||
samples_end = samples + samples_size - n;
|
||||
q = samples_end + n;
|
||||
|
||||
while(nb > 0)
|
||||
{
|
||||
memcpy(q, samples_end, n);
|
||||
q += n;
|
||||
nb -= n;
|
||||
}
|
||||
|
||||
samples_size = wanted_size;
|
||||
}
|
||||
}
|
||||
|
@ -235,38 +242,47 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder
|
|||
return samples_size;
|
||||
}
|
||||
|
||||
int audio_decode_frame(uint8_t *audio_buf, int buf_size, double *pts_ptr)
|
||||
int audio_decode_frame(AVFrame *frame, double *pts_ptr)
|
||||
{
|
||||
AVPacket *pkt = &is->audio_pkt;
|
||||
int len1, data_size, n;
|
||||
double pts;
|
||||
int len1, data_size;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
while(is->audio_pkt_size > 0)
|
||||
while(pkt->size > 0)
|
||||
{
|
||||
data_size = buf_size;
|
||||
int got_frame;
|
||||
|
||||
len1 = avcodec_decode_audio3(is->audio_st->codec,
|
||||
(int16_t*)audio_buf, &data_size, pkt);
|
||||
if(len1 < 0)
|
||||
len1 = avcodec_decode_audio4(is->audio_st->codec, frame, &got_frame, pkt);
|
||||
if(len1 < 0 || len1 > pkt->size)
|
||||
{
|
||||
/* if error, skip frame */
|
||||
is->audio_pkt_size = 0;
|
||||
/* if error, skip packet */
|
||||
break;
|
||||
}
|
||||
is->audio_pkt_data += len1;
|
||||
is->audio_pkt_size -= len1;
|
||||
|
||||
if(len1 <= pkt->size)
|
||||
{
|
||||
/* Move the unread data to the front and clear the end bits */
|
||||
int remaining = pkt->size - len1;
|
||||
memmove(pkt->data, &pkt->data[len1], remaining);
|
||||
memset(&pkt->data[remaining], 0, pkt->size - remaining);
|
||||
pkt->size -= len1;
|
||||
}
|
||||
if(!got_frame)
|
||||
continue;
|
||||
|
||||
int smp_size = av_samples_get_buffer_size(NULL, is->audio_st->codec->channels, 1,
|
||||
is->audio_st->codec->sample_fmt, 1);
|
||||
data_size = frame->nb_samples * smp_size;
|
||||
if(data_size <= 0)
|
||||
{
|
||||
/* No data yet, get more frames */
|
||||
continue;
|
||||
}
|
||||
pts = is->audio_clock;
|
||||
*pts_ptr = pts;
|
||||
n = 2 * is->audio_st->codec->channels;
|
||||
is->audio_clock += (double)data_size /
|
||||
(double)(n * is->audio_st->codec->sample_rate);
|
||||
|
||||
*pts_ptr = is->audio_clock;
|
||||
is->audio_clock += (double)(data_size/smp_size) /
|
||||
(double)is->audio_st->codec->sample_rate;
|
||||
|
||||
/* We have data, return it and come back for more later */
|
||||
return data_size;
|
||||
|
@ -281,8 +297,6 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder
|
|||
if(packet_queue_get(&is->audioq, pkt, is, 1) < 0)
|
||||
return -1;
|
||||
|
||||
is->audio_pkt_data = pkt->data;
|
||||
is->audio_pkt_size = pkt->size;
|
||||
/* if update, update the audio clock w/pts */
|
||||
if((uint64_t)pkt->pts != AV_NOPTS_VALUE)
|
||||
is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
|
||||
|
@ -300,7 +314,16 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder
|
|||
void rewind() { }
|
||||
|
||||
public:
|
||||
MovieAudioDecoder(VideoState *_is) : is(_is) { }
|
||||
MovieAudioDecoder(VideoState *_is)
|
||||
: is(_is)
|
||||
, mFrame(avcodec_alloc_frame())
|
||||
, mFramePos(0)
|
||||
, mFrameSize(0)
|
||||
{ }
|
||||
virtual ~MovieAudioDecoder()
|
||||
{
|
||||
av_freep(&mFrame);
|
||||
}
|
||||
|
||||
void getInfo(int *samplerate, MWSound::ChannelConfig *chans, MWSound::SampleType * type)
|
||||
{
|
||||
|
@ -353,30 +376,29 @@ public:
|
|||
|
||||
while(total < len)
|
||||
{
|
||||
if(is->audio_buf_index >= is->audio_buf_size)
|
||||
if(mFramePos >= mFrameSize)
|
||||
{
|
||||
int audio_size;
|
||||
double pts;
|
||||
|
||||
/* We have already sent all our data; get more */
|
||||
audio_size = audio_decode_frame(is->audio_buf, sizeof(is->audio_buf), &pts);
|
||||
audio_size = audio_decode_frame(mFrame, &pts);
|
||||
if(audio_size < 0)
|
||||
{
|
||||
/* If error, we're done */
|
||||
break;
|
||||
}
|
||||
|
||||
audio_size = synchronize_audio(is->audio_buf, audio_size, pts);
|
||||
is->audio_buf_size = audio_size;
|
||||
is->audio_buf_index = 0;
|
||||
mFrameSize = synchronize_audio(mFrame->data[0], audio_size, pts);
|
||||
mFramePos = 0;
|
||||
}
|
||||
|
||||
size_t len1 = std::min<size_t>(is->audio_buf_size - is->audio_buf_index,
|
||||
len - total);
|
||||
memcpy(stream, (uint8_t*)is->audio_buf + is->audio_buf_index, len1);
|
||||
size_t len1 = std::min<size_t>(len - total, mFrameSize-mFramePos);
|
||||
memcpy(stream, mFrame->data[0]+mFramePos, len1);
|
||||
|
||||
total += len1;
|
||||
stream += len1;
|
||||
is->audio_buf_index += len1;
|
||||
mFramePos += len1;
|
||||
}
|
||||
|
||||
return total;
|
||||
|
@ -670,8 +692,6 @@ public:
|
|||
case AVMEDIA_TYPE_AUDIO:
|
||||
is->audioStream = stream_index;
|
||||
is->audio_st = pFormatCtx->streams[stream_index];
|
||||
is->audio_buf_size = 0;
|
||||
is->audio_buf_index = 0;
|
||||
|
||||
/* averaging filter for audio sync */
|
||||
is->audio_diff_avg_coef = exp(log(0.01 / AUDIO_DIFF_AVG_NB));
|
||||
|
|
|
@ -58,11 +58,11 @@ namespace MWRender
|
|||
struct VideoState {
|
||||
VideoState () :
|
||||
videoStream(-1), audioStream(-1), av_sync_type(0), external_clock(0),
|
||||
external_clock_time(0), audio_clock(0), audio_st(NULL), audio_buf_size(0),
|
||||
audio_pkt_data(NULL), audio_pkt_size(0), audio_diff_cum(0), audio_diff_avg_coef(0),
|
||||
audio_diff_threshold(0), audio_diff_avg_count(0), frame_timer(0), frame_last_pts(0), frame_last_delay(0),
|
||||
video_clock(0), video_current_pts(0), video_current_pts_time(0), video_st(NULL), rgbaFrame(NULL), pictq_size(0),
|
||||
pictq_rindex(0), pictq_windex(0), quit(false), refresh(0), format_ctx(0), sws_context(NULL), display_ready(0)
|
||||
external_clock_time(0), audio_clock(0), audio_st(NULL), audio_diff_cum(0),
|
||||
audio_diff_avg_coef(0), audio_diff_threshold(0), audio_diff_avg_count(0), frame_timer(0),
|
||||
frame_last_pts(0), frame_last_delay(0), video_clock(0), video_current_pts(0),
|
||||
video_current_pts_time(0), video_st(NULL), rgbaFrame(NULL), pictq_size(0), pictq_rindex(0),
|
||||
pictq_windex(0), quit(false), refresh(0), format_ctx(0), sws_context(NULL), display_ready(0)
|
||||
{}
|
||||
|
||||
|
||||
|
@ -84,12 +84,7 @@ namespace MWRender
|
|||
double audio_clock;
|
||||
AVStream *audio_st;
|
||||
PacketQueue audioq;
|
||||
DECLARE_ALIGNED(16, uint8_t, audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
|
||||
unsigned int audio_buf_size;
|
||||
unsigned int audio_buf_index;
|
||||
AVPacket audio_pkt;
|
||||
uint8_t *audio_pkt_data;
|
||||
int audio_pkt_size;
|
||||
double audio_diff_cum; /* used for AV difference average computation */
|
||||
double audio_diff_avg_coef;
|
||||
double audio_diff_threshold;
|
||||
|
|
Loading…
Reference in a new issue