#include "fillplugins.h" #include "FFAudioDecoder.h" #include "FFVideoDecoder.h" #include "FFVideoEncoder.h" #include "videoencoder.h" #include "avm_output.h" #include "plugin.h" #include #include AVM_BEGIN_NAMESPACE; PLUGIN_TEMP(ffmpeg); #if 0 class FFVideoDec: public IVideoDecoder { public: FFVideoDec(AVCodec* av,const CodecInfo& info, const BITMAPINFOHEADER& format, int flip); :IVideoDecoder(info, bh), m_pAvCodec(av), m_Caps(CAP_YV12), m_bOpened(false) { m_Dest.SetSpace(fccYV12); if (flip) m_Dest.biHeight *= -1; if (avcodec(0, AVCODEC_OPEN_BY_FCC, (void*)info.fourcc, &m_pHandle) < 0) throw; AVM_WRITE("FFMPEG video decoder", "opened\n"); } virtual ~FFVideoDec(); { Stop(); } virtual int DecodeFrame(CImage* pImage, const void* src, uint_t size, int is_keyframe, bool render = true); { if (!m_bOpened) { memset(&m_AvContext, 0, sizeof(AVCodecContext)); m_AvContext.width = m_Dest.biWidth; m_AvContext.height = labs(m_Dest.biHeight); m_AvContext.pix_fmt = PIX_FMT_YUV422; if (avcodec_open(&m_AvContext, m_pAvCodec) < 0) { AVM_WRITE("FFMPEG video decoder", "WARNING: FFVideoDecoder::DecodeFrame() can't open avcodec\n"); return -1; } else m_bOpened = true; } while (size > 0) { int got_picture = 0; int hr = avcodec_decode_video(&m_AvContext, &m_AvPicture, &got_picture, (unsigned char*) src, size); if (hr < 0) { AVM_WRITE("FFMPEG video decoder", "WARNING: FFVideoDecoder::DecodeFrame() hr=%d\n", hr); return hr; } //printf("DECFF got_picture %d %p %d del:%d hr:%d\n" , got_picture, src, size, m_AvContext.delay, hr); if (!got_picture) return hr + 1; int imfmt; switch (m_AvContext.pix_fmt) { case PIX_FMT_YUV420P: imfmt = IMG_FMT_I420; break; case PIX_FMT_YUV422: imfmt = IMG_FMT_I420; break; case PIX_FMT_RGB24: imfmt = IMG_FMT_RGB24; break; case PIX_FMT_BGR24: imfmt = IMG_FMT_BGR24; break; case PIX_FMT_YUV422P: imfmt = IMG_FMT_Y422; break; case PIX_FMT_YUV444P: imfmt = IMG_FMT_IYU2; break; default: AVM_WRITE("FFMPEG video decoder", "Unknown colorspace\n"); return -1; } //printf("CONTEXT %d %x %.4s\n", got_picture, m_AvContext.pix_fmt, (char*)&imfmt); if (got_picture && pImage && render) { BitmapInfo bi(m_Dest); bi.SetSpace(imfmt); //printf("LINE %d %d %d\n", m_AvPicture.linesize[0], m_AvPicture.linesize[1], m_AvPicture.linesize[2]); //printf("LINE %p %p %p\n", m_AvPicture.data[0], m_AvPicture.data[1], m_AvPicture.data[2]); CImage ci(&bi, (const uint8_t**) m_AvPicture.data, m_AvPicture.linesize, false); pImage->Convert(&ci); //printf("xxx %p\n", m_AvPicture.data[0]); //memcpy(pImage->Data(), m_AvPicture.data[0], 320 * 50); } size -= hr; src = (const char*) src + hr; } return 0; } virtual CAPS GetCapabilities() const { return m_Caps; } virtual void Flush(); { if (m_bOpened) avcodec_flush_buffers(&m_AvContext); } virtual int SetDestFmt(int bits = 24, fourcc_t csp = 0); { if (!CImage::Supported(csp, bits) || csp != fccYV12) return -1; Restart(); return 0; } virtual int Stop(); { if (m_bOpened) avcodec_close(&m_AvContext); m_bOpened = false; return 0; } protected: void* m_pHandle; AVPicture m_AvPicture; CAPS m_Caps; bool m_bOpened; bool m_bFlushed; }; #endif // figure out which codec we need to use static void av_init() { static int is_init = 0; if (!is_init) { avcodec_init(); avcodec_register_all(); is_init++; } } static IVideoEncoder* ffmpeg_CreateVideoEncoder(const CodecInfo& info, fourcc_t compressor, const BITMAPINFOHEADER& bh) { av_init(); AVCodec* av = avcodec_find_encoder_by_name(info.dll.c_str()); if (av) { switch (bh.biCompression) { case 0: case fccYUY2: case fccYV12: case fccI420: case fccDIVX: case fccDX50: return new FFVideoEncoder(av, info, compressor, bh); default: ffmpeg_error_set("unsupported input format"); } } else ffmpeg_error_set("video codec not found"); return 0; } static IVideoDecoder* ffmpeg_CreateVideoDecoder(const CodecInfo& info, const BITMAPINFOHEADER& bh, int flip) { av_init(); AVCodec* av = avcodec_find_decoder_by_name(info.dll.c_str()); if (av) return new FFVideoDecoder(av, info, bh, flip); ffmpeg_error_set("video codec not found"); return 0; } static IAudioDecoder* ffmpeg_CreateAudioDecoder(const CodecInfo& info, const WAVEFORMATEX* fmt) { av_init(); AVCodec* av = avcodec_find_decoder_by_name(info.dll.c_str()); if (av) return new FFAudioDecoder(av, info, fmt); ffmpeg_error_set("audio codec not found"); return 0; } AVM_END_NAMESPACE; extern "C" const avm::codec_plugin_t avm_codec_plugin_ffmpeg = { PLUGIN_API_VERSION, 0, avm::PluginGetAttrFloat, avm::PluginSetAttrFloat, avm::PluginGetAttrInt, avm::PluginSetAttrInt, avm::PluginGetAttrString, avm::PluginSetAttrString, avm::ffmpeg_FillPlugins, avm::ffmpeg_CreateAudioDecoder, 0, avm::ffmpeg_CreateVideoDecoder, avm::ffmpeg_CreateVideoEncoder, };