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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user