1
#include "FFVideoDecoder.h"
2
#include "fillplugins.h"
4
#include "avm_output.h"
7
#include <stdlib.h> // free
12
#include "avm_cpuinfo.h"
23
FFVideoDecoder::FFVideoDecoder(AVCodec* av, const CodecInfo& info, const BITMAPINFOHEADER& bh, int flip)
24
:IVideoDecoder(info, bh), m_pAvCodec(av), m_pAvContext(0),
25
m_Caps((CAPS)(CAP_YV12 | CAP_ALIGN16)), m_uiBuffers(0), m_bRestart(true),
26
m_Order(20), m_pImg(0), m_bUsed(false)
28
m_Dest.SetSpace(fccYV12);
29
// not supported if (flip) m_Dest.biHeight *= -1;
32
//m_pAvStream = (struct AVStream*)bh.biXPelsPerMeter; Debug printf("Context %p\n", m_pAvStream);
33
if (0 && m_pFormat->biCompression == fccHFYU)
36
m_pAvCodec->capabilities &= ~(CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1);
37
AVM_WRITE(m_Info.GetPrivateName(), "if you have troubles - use Win32 codec instead\n");
38
m_Caps = (CAPS) (m_Caps | CAP_YUY2);
42
FFVideoDecoder::~FFVideoDecoder()
45
FFTIMING(printf("ftm %f\n", ftm));
48
void FFVideoDecoder::Flush()
50
Debug printf("\nFF: Flush\n\n");
52
avcodec_flush_buffers(m_pAvContext);
55
//m_iAgeB = m_iAgeIP[0] = m_iAgeIP[1] = (1 << 30);
58
// callback to draw horizontal slice
59
static void draw_slice(struct AVCodecContext *avctx,
60
const AVFrame *src, int offset[4],
61
int y, int type, int height)
63
FFVideoDecoder* d = (FFVideoDecoder*) avctx->opaque;
65
ci.m_pPlane[0] = src->data[0] + offset[0];
66
ci.m_pPlane[1] = src->data[2] + offset[2];
67
ci.m_pPlane[2] = src->data[1] + offset[1];
68
ci.m_iStride[0] = src->linesize[0];
69
ci.m_iStride[1] = src->linesize[2];
70
ci.m_iStride[2] = src->linesize[1];
71
ci.m_iWidth = ci.m_Window.w = avctx->width;
72
ci.m_iHeight = ci.m_Window.h = height;
75
ci.m_iFormat = IMG_FMT_YV12;
76
//printf("DrawSlice %p %p y:%d w:%d h:%d\n", d->m_pImg, src, ci.m_Window.y, ci.m_Window.w, height);
77
d->m_pImg->Slice(&ci);
80
// callback to supply rendering buffer to ffmpeg
81
static int get_buffer(AVCodecContext* avctx, AVFrame* pic)
83
static const char ftypes[][3] = { "I", "P", "B", "S", "SI", "SP" };
85
FFVideoDecoder* d = (FFVideoDecoder*) avctx->opaque;
86
CImage* pImage = d->m_pImg;
87
if ((avctx->pix_fmt != PIX_FMT_YUV420P
88
&& avctx->pix_fmt != PIX_FMT_YUVJ420P)
89
|| !pImage || !d->m_bDirect)
91
Debug printf("FF: Unsupported pixel format for Dr1 %d\n", avctx->pix_fmt); //abort();
92
return avcodec_default_get_buffer(avctx, pic);
96
Debug if (pic->buffer_hints) printf("FF bufhints 0x%x\n", pic->buffer_hints);
101
const uint8_t b[3] = { 0x10, 0x80, 0x80 };
102
for (int j = 0; j < 3; ++j) {
104
fprintf(stderr, "CLEANbuff b:%d p:%p c:%x\n", pImage->Stride(j), pImage->Data(j), c);
105
for (unsigned i = 0; i < pImage->Stride(j); ++i) pImage->Data(j)[i] = c;
109
// we are using YV12 - ffmpeg uses I420
110
pic->data[0] = pImage->Data(0);
111
pic->data[1] = pImage->Data(2);
112
pic->data[2] = pImage->Data(1);
113
pic->linesize[0] = pImage->Stride(0);
114
pic->linesize[1] = pImage->Stride(2); // Note: for ffmpeg linsize[1] == linesize[2]!
115
pic->linesize[2] = pImage->Stride(1);
116
pic->pts = pImage->m_lTimestamp;
117
pic->type = FF_BUFFER_TYPE_USER;
118
pImage->m_iType = pic->pict_type;
120
pic->age = (pImage->GetAge() != pImage->MAX_AGE) ? pic->coded_picture_number - pImage->GetAge() : (1 << 30);
122
pImage->Age(pic->coded_picture_number);
126
Debug printf("FF: <<<< GetBuffer %p %s %dx%d %p:%p:%p s:%f f:%d r:%d age:%d\n", pImage, ftypes[pic->pict_type],
127
avctx->width, avctx->height, pImage->Data(0), pImage->Data(2), pImage->Data(1),
128
(double)pImage->m_lTimestamp / 1000000., avctx->pix_fmt, pic->reference, pic->age);
132
static void release_buffer(struct AVCodecContext* avctx, AVFrame* pic)
134
if (pic->type == FF_BUFFER_TYPE_USER)
136
FFVideoDecoder* d = (FFVideoDecoder*) avctx->opaque;
137
d->m_pReleased = (CImage*) pic->opaque;
138
Debug printf("FF: >>>> Released buffer %p %p\n", pic->opaque, pic);
139
memset(pic->data, 0, sizeof(void*) * 4);
144
Debug printf(">>>> released default buffer *****************\n");
145
avcodec_default_release_buffer(avctx, pic);
149
int FFVideoDecoder::DecodeFrame(CImage* pImage, const void* src, size_t size,
150
int is_keyframe, bool render, CImage** pOut)
152
FFTIMING(int64_t ts = avm_get_time_us());
153
if (//(m_bFlushed && !is_keyframe) ||
154
(pImage && pImage->GetAllocator()
155
&& m_uiBuffers != pImage->GetAllocator()->GetImages())
158
//printf("RES %d %" PRIsz " %" PRIsz "\n", m_bRestart, m_uiBuffers, pImage->GetAllocator()->GetImages());
162
//printf("FFMPEG space %p \n", m_pAvContext); m_Dest.Print(); pImage->GetFmt()->Print();
165
if (!(m_pAvContext = avcodec_alloc_context2(m_pAvCodec->type)))
167
// for autodetection errors
168
m_pAvContext->codec_tag = m_pFormat->biCompression;
169
m_pAvContext->bits_per_coded_sample = m_pFormat->biBitCount;
170
m_pAvContext->width = m_Dest.biWidth;
171
m_pAvContext->height = (m_Dest.biHeight < 0) ? -m_Dest.biHeight : m_Dest.biHeight;
173
if (m_pFormat->biSize > sizeof(BITMAPINFOHEADER))
175
m_pAvContext->extradata_size = int(m_pFormat->biSize - sizeof(BITMAPINFOHEADER));
176
m_pAvContext->extradata = (uint8_t*)m_pFormat + sizeof(BITMAPINFOHEADER);
177
if (m_pAvContext->extradata_size > 40)
178
m_pAvContext->flags |= CODEC_FLAG_EXTERN_HUFF; // somewhat useless
181
m_uiBuffers = (pImage && pImage->GetAllocator()) ? pImage->GetAllocator()->GetImages() : 0;
182
//printf("IMAGES %d\n", m_uiBuffers);
183
// for SVQ1 - align 63 will be needed FIXME
185
const char* drtxt = "doesn't support";
188
if (m_pAvCodec->capabilities & CODEC_CAP_DR1)
194
//fprintf(stderr, "buff %" PRIsz " %" PRIsz "\n", m_uiBuffers, require);
195
switch (m_Info.fourcc)
201
if (m_Info.FindAttribute(ffstr_dr1)
202
&& PluginGetAttrInt(m_Info, ffstr_dr1, &v) == 0 && v
203
&& pImage->Format() == IMG_FMT_YV12)
205
// for DR we needs some special width aligment
206
// also there are some more limitation
207
m_pAvContext->flags |= CODEC_FLAG_EMU_EDGE;
210
//m_pAvContext->skip_top = 32;
212
m_pAvContext->skip_loop_filter = AVDISCARD_BIDIR;
213
m_pAvContext->skip_idct = AVDISCARD_BIDIR;
214
m_pAvContext->skip_frame = AVDISCARD_BIDIR;
216
m_pAvContext->get_buffer = get_buffer;
217
m_pAvContext->reget_buffer = get_buffer;
218
m_pAvContext->release_buffer = release_buffer;
223
AVM_WRITE(m_Info.GetPrivateName(), "%s DR1\n", drtxt);
227
if (m_Info.fourcc == RIFFINFO_MPG1
228
&& m_pAvCodec->capabilities & CODEC_CAP_TRUNCATED)
229
m_pAvContext->flags |= CODEC_FLAG_TRUNCATED;
233
m_pAvContext->error_recognition = FF_ER_COMPLIANT;
234
m_pAvContext->error_concealment = FF_EC_GUESS_MVS;
235
m_pAvContext->workaround_bugs = FF_BUG_AUTODETECT;
238
if (codec->options) {
239
avm::vector<AttributeInfo>::const_iterator it;
240
for (it = m_Info.decoder_info.begin();
241
it != m_Info.decoder_info.end(); it++)
246
switch (it->GetKind())
248
case AttributeInfo::Integer:
249
PluginGetAttrInt(m_Info, it->GetName(), &v);
250
sprintf(b, "%s=%d", it->GetName(), v);
252
case AttributeInfo::Float:
253
PluginGetAttrFloat(m_Info, it->GetName(), &f);
254
sprintf(b, "%s=%f", it->GetName(), f);
259
Debug printf("pass options '%s': %s\n", it->GetName(), b);
260
avoption_parse(m_pAvContext, codec->options, b);
265
static const struct fftable {
269
{ ffstr_bug_old_msmpeg4, FF_BUG_OLD_MSMPEG4 },
270
{ ffstr_bug_xvid_ilace, FF_BUG_XVID_ILACE },
271
{ ffstr_bug_ump4, FF_BUG_UMP4 },
272
{ ffstr_bug_no_padding, FF_BUG_NO_PADDING },
273
{ ffstr_bug_ac_vlc, FF_BUG_AC_VLC },
274
{ ffstr_bug_qpel_chroma, FF_BUG_QPEL_CHROMA },
277
for (const struct fftable* p = fftab; p->attr; p++)
279
if (m_Info.FindAttribute(p->attr)
280
&& PluginGetAttrInt(m_Info, p->attr, &v) == 0 && v)
281
m_pAvContext->workaround_bugs |= p->flag;
284
if (avcodec_open(m_pAvContext, m_pAvCodec) < 0)
286
AVM_WRITE(m_Info.GetPrivateName(), "WARNING: FFVideoDecoder::DecodeFrame() can't open avcodec\n");
292
// try using draw_horiz_band if DR1 is unsupported
293
m_pAvContext->draw_horiz_band =
294
(!m_bDirect && pImage && pImage->Format() == IMG_FMT_YV12
295
&& (m_pAvCodec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND)
296
&& !pImage->Direction() && render) ? draw_slice : 0;
297
m_pAvContext->opaque = this;
299
Debug printf("FF: Decode start %p pkt size: %" PRIsz " horiz:%d\n", pImage, size, (m_pAvContext->draw_horiz_band != 0));
307
av_init_packet(&avpkt);
308
avpkt.data = (uint8_t*)src;
309
avpkt.size = (int)size;
311
int hr = avcodec_decode_video2(m_pAvContext, &pic, &got_picture, &avpkt);
312
//printf("DECFF got_picture %d %p del:%d hr:%d size:%d\n", got_picture, src, m_pAvContext->delay, hr, size);
313
//printf("PictType %d\n", m_pAvContext->pict_type);
314
//static int ctr=0; printf("WIDTH %dx%d %d r:%d\n", m_pAvContext->width, m_pAvContext->height, ctr++, m_pAvContext->pict_type);
315
Debug printf("FF: Decoded used=%d got_pic=%d res=%d\n", m_bUsed, got_picture, hr);
318
AVM_WRITE(m_Info.GetPrivateName(), "WARNING: FFVideoDecoder::DecodeFrame() hr=%d\n", hr);
321
if (!(m_pAvContext->flags & CODEC_FLAG_TRUNCATED))
327
if (!m_bDirect || m_bUsed)
329
size_t i = m_Order.size();
334
timestamp = pImage->m_lTimestamp;
335
position = pImage->m_uiPosition;
338
// keep data ordered by timestamps
339
if (timestamp > m_Order[i - 1].timestamp)
349
Debug printf("FF: Insert %" PRIsz " %" PRId64 " %" PRId64 " gotpic:%d\n", i, timestamp, m_Order[i].timestamp, got_picture);
350
m_Order.insert(i, fpair(timestamp, position));
356
Debug printf("FF: r=0x%x sz=%" PRIsz " %d b:%d img:%p out:%p\n", hr, size, got_picture, m_bUsed, pImage, pOut);
357
Debug printf("FF: frame_size %d number %d picnum %d\n", m_pAvContext->frame_size, m_pAvContext->frame_number, m_pAvContext->real_pict_num);
360
Debug printf("FF: NO PICTURE released=%p\n", m_pReleased);
362
return hr | NO_PICTURE;
363
// let's fake got_picture;
365
pic.type = FF_BUFFER_TYPE_USER;
366
pic.opaque = m_pReleased;
371
//printf("CONTEXT %d %x %.4s\n", got_picture, m_pAvContext->pix_fmt, (char*)&imfmt);
373
if (render && pImage && got_picture && !m_bDirect
374
&& !m_pAvContext->draw_horiz_band)
377
Debug printf("PIXFMPT %d\n", m_pAvContext->pix_fmt);
378
switch (m_pAvContext->pix_fmt)
380
case PIX_FMT_BGR24: imfmt = IMG_FMT_BGR24; break;
381
case PIX_FMT_RGBA: imfmt = IMG_FMT_BGR32; break;
382
case PIX_FMT_YUYV422: imfmt = IMG_FMT_YUY2; break;
383
case PIX_FMT_YUV410P: imfmt = IMG_FMT_I410; break;
384
case PIX_FMT_YUV411P: imfmt = IMG_FMT_I411; break;
385
case PIX_FMT_YUV420P: imfmt = IMG_FMT_I420; break;
386
case PIX_FMT_YUVJ420P: imfmt = IMG_FMT_I420; break; // strange
387
case PIX_FMT_YUV422P: imfmt = IMG_FMT_I422; break;
388
case PIX_FMT_YUV444P: imfmt = IMG_FMT_I444; break;
392
BitmapInfo bi(m_Dest);
395
//printf("FFMPEG SETSPACE\n"); pImage->GetFmt()->Print(); bi.Print();
396
//printf("LINE %d %d %d\n", pic.linesize[0], pic.linesize[1], pic.linesize[2]);
397
//printf("LINE %p %p %p\n", pic.data[0], pic.data[1], pic.data[2]);
398
CImage ci(&bi, const_cast<const uint8_t**>(pic.data), pic.linesize, false);
399
pImage->Convert(&ci);
400
//printf("xxx %p\n", m_AvPicture.data[0]);
401
//memcpy(pImage->Data(), pic.data[0], 320 * 150);
403
AVM_WRITE(m_Info.GetPrivateName(), "Unsupported colorspace: %d, FIXME\n", m_pAvContext->pix_fmt);
408
//printf("SWAP %lld %lld\n", m_Order.front().timestamp, pImage->m_lTimestamp);
409
//printf("SWAP %d %d\n", m_Order.front().position, pImage->m_uiPosition);
410
//printf("P %d %lld\n", p, m_Order[0].timestamp, m_Order.size());
412
Debug printf("FF: release:%p out:%p tuc:%d(%d/%d)\n", m_pReleased, pOut, pic.type, FF_BUFFER_TYPE_USER, FF_BUFFER_TYPE_COPY);
414
if (pOut && pic.opaque &&
415
((pic.type == FF_BUFFER_TYPE_USER)
416
|| (pic.type == FF_BUFFER_TYPE_COPY)))
418
*pOut = (CImage*) pic.opaque;
419
(*pOut)->m_lTimestamp = m_Order[0].timestamp;
420
(*pOut)->m_uiPosition = m_Order[0].position;
424
pImage->m_lTimestamp = m_Order[0].timestamp;
425
pImage->m_uiPosition = m_Order[0].position;
430
//printf("OUT %d %p\n", got_picture, *pOut);
432
FFTIMING(ftm += avm_get_time_diff(avm_get_time_us(), ts));
433
Debug printf("FF: pictype %d time:%f c:%d d:%d %" PRId64 " %p\n", pic.pict_type, (double) pic.pts / 1000000.,
434
pic.coded_picture_number, pic.display_picture_number, pImage->m_lTimestamp, pic.opaque);
435
//pImage->m_lTimestamp = pic.pts / (double) AV_TIME_BASE;
440
int FFVideoDecoder::SetDestFmt(int bits, fourcc_t csp)
442
if (!CImage::Supported(csp, bits) || csp != fccYV12)
449
int FFVideoDecoder::Stop()
453
avcodec_close(m_pAvContext);
460
const avm::vector<AttributeInfo>& FFVideoDecoder::GetAttrs() const
462
return m_Info.decoder_info;
465
int FFVideoDecoder::GetValue(const char* name, int* value) const
467
return PluginGetAttrInt(m_Info, name, value);
469
int FFVideoDecoder::SetValue(const char* name, int value)
471
int r = PluginSetAttrInt(m_Info, name, value);
472
m_bRestart = (r == 0);