1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-12-13 16:16:33 +01:00

integrate OD FFmpeg to work with multiple formats, including wav

also move streamContext to ffmpeg.h to allow for refactoring of import code
This commit is contained in:
mchinen
2012-06-01 06:11:07 +00:00
parent 8cb2a38fbe
commit 816b58bc08
5 changed files with 228 additions and 296 deletions

View File

@@ -162,36 +162,7 @@ static const wxChar *exts[] =
extern FFmpegLibs *FFmpegLibsInst;
class FFmpegImportFileHandle;
//moving from ImportFFmpeg.cpp to FFMpeg.h so other cpp files can use this struct.
#ifndef EXPERIMENTAL_OD_FFMPEG
typedef struct _streamContext
{
bool m_use; // TRUE = this stream will be loaded into Audacity
AVStream *m_stream; // an AVStream *
AVCodecContext *m_codecCtx; // pointer to m_stream->codec
AVPacket m_pkt; // the last AVPacket we read for this stream
int m_pktValid; // is m_pkt valid?
uint8_t *m_pktDataPtr; // pointer into m_pkt.data
int m_pktRemainingSiz;
int64_t m_pts; // the current presentation time of the input stream
int64_t m_ptsOffset; // packets associated with stream are relative to this
int m_frameValid; // is m_decodedVideoFrame/m_decodedAudioSamples valid?
uint8_t *m_decodedAudioSamples; // decoded audio samples stored here
unsigned int m_decodedAudioSamplesSiz; // current size of m_decodedAudioSamples
int m_decodedAudioSamplesValidSiz; // # valid bytes in m_decodedAudioSamples
int m_initialchannels; // number of channels allocated when we begin the importing. Assumes that number of channels doesn't change on the fly.
int m_samplesize; // input sample size in bytes
SampleFormat m_samplefmt; // input sample format
int m_osamplesize; // output sample size in bytes
sampleFormat m_osamplefmt; // output sample format
} streamContext;
#endif
/// A representative of FFmpeg loader in
/// the Audacity import plugin list
class FFmpegImportPlugin : public ImportPlugin
@@ -730,128 +701,12 @@ int FFmpegImportFileHandle::Import(TrackFactory *trackFactory,
streamContext *FFmpegImportFileHandle::ReadNextFrame()
{
streamContext *sc = NULL;
AVPacket pkt;
if (av_read_frame(mFormatContext,&pkt) < 0)
{
return NULL;
}
// Find a stream to which this frame belongs to
for (int i = 0; i < mNumStreams; i++)
{
if (mScs[i]->m_stream->index == pkt.stream_index)
sc = mScs[i];
}
// Off-stream packet. Don't panic, just skip it.
// When not all streams are selected for import this will happen very often.
if (sc == NULL)
{
av_free_packet(&pkt);
return (streamContext*)1;
}
// Copy the frame to the stream context
memcpy(&sc->m_pkt, &pkt, sizeof(AVPacket));
sc->m_pktValid = 1;
sc->m_pktDataPtr = pkt.data;
sc->m_pktRemainingSiz = pkt.size;
return sc;
return import_ffmpeg_read_next_frame(mFormatContext, mScs, mNumStreams);
}
int FFmpegImportFileHandle::DecodeFrame(streamContext *sc, bool flushing)
{
int nBytesDecoded;
wxUint8 *pDecode = sc->m_pktDataPtr;
int nDecodeSiz = sc->m_pktRemainingSiz;
sc->m_frameValid = 0;
if (flushing)
{
// If we're flushing the decoders we don't actually have any new data to decode.
pDecode = NULL;
nDecodeSiz = 0;
}
else
{
if (!sc->m_pktValid || (sc->m_pktRemainingSiz <= 0))
{
//No more data
return -1;
}
}
sc->m_samplefmt = sc->m_codecCtx->sample_fmt;
sc->m_samplesize = av_get_bits_per_sample_fmt(sc->m_samplefmt) / 8;
unsigned int newsize = FFMAX(sc->m_pkt.size * sc->m_samplesize, AVCODEC_MAX_AUDIO_FRAME_SIZE);
// Reallocate the audio sample buffer if it's smaller than the frame size.
if (newsize > sc->m_decodedAudioSamplesSiz )
{
if (sc->m_decodedAudioSamples)
{
av_free(sc->m_decodedAudioSamples);
}
sc->m_decodedAudioSamples = (uint8_t *) av_malloc(newsize);
sc->m_decodedAudioSamplesSiz = newsize;
if (sc->m_decodedAudioSamples == NULL)
{
//Can't allocate bytes
return -1;
}
}
sc->m_decodedAudioSamplesValidSiz = sc->m_decodedAudioSamplesSiz;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 25, 0)
// avcodec_decode_audio3() expects the size of the output buffer as the 3rd parameter but
// also returns the number of bytes it decoded in the same parameter.
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = pDecode;
avpkt.size = nDecodeSiz;
nBytesDecoded =
avcodec_decode_audio3(sc->m_codecCtx,
(int16_t *)sc->m_decodedAudioSamples, // out
&sc->m_decodedAudioSamplesValidSiz, // in/out
&avpkt); // in
#else
// avcodec_decode_audio2() expects the size of the output buffer as the 3rd parameter but
// also returns the number of bytes it decoded in the same parameter.
nBytesDecoded =
avcodec_decode_audio2(sc->m_codecCtx,
(int16_t *) sc->m_decodedAudioSamples, // out
&sc->m_decodedAudioSamplesValidSiz, // in/out
pDecode, // in
nDecodeSiz); // in
#endif
if (nBytesDecoded < 0)
{
// Decoding failed. Don't stop.
return -1;
}
// We may not have read all of the data from this packet. If so, the user can call again.
// Whether or not they do depends on if m_pktRemainingSiz == 0 (they can check).
sc->m_pktDataPtr += nBytesDecoded;
sc->m_pktRemainingSiz -= nBytesDecoded;
// At this point it's normally safe to assume that we've read some samples. However, the MPEG
// audio decoder is broken. If this is the case then we just return with m_frameValid == 0
// but m_pktRemainingSiz perhaps != 0, so the user can call again.
if (sc->m_decodedAudioSamplesValidSiz > 0)
{
sc->m_frameValid = 1;
}
return 0;
return import_ffmpeg_decode_frame(sc, flushing);
}
int FFmpegImportFileHandle::WriteData(streamContext *sc)