Permalink
Browse files

fixed: pixelformat conversion for non yuv data would often fail for d…

…vdplayer

changed: simplified code to allocate conversion picture
changed: added hack which allocates one extra line of data for the conversion buffer

git-svn-id: http://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/linuxport/XBMC@19144 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
  • Loading branch information...
1 parent 307aa14 commit 8131ed87fc2505083e7295e262e3873059e805fb elupus committed with elan Apr 2, 2009
@@ -141,10 +141,9 @@ void CDVDVideoCodecFFmpeg::Dispose()
m_pFrame = NULL;
if (m_pConvertFrame)
+
{
- delete[] m_pConvertFrame->data[0];
- if(m_pConvertFrame->opaque)
- free(m_pConvertFrame->opaque);
+ m_dllAvCodec.avpicture_free(m_pConvertFrame);
m_dllAvUtil.av_free(m_pConvertFrame);
}
m_pConvertFrame = NULL;
@@ -259,41 +258,40 @@ int CDVDVideoCodecFFmpeg::Decode(BYTE* pData, int iSize, double pts)
if (!m_pConvertFrame)
{
// Allocate an AVFrame structure
- m_pConvertFrame = m_dllAvCodec.avcodec_alloc_frame();
-
- // Determine required buffer size and allocate buffer
- int numBytes = m_dllAvCodec.avpicture_get_size(PIX_FMT_YUV420P, m_pCodecContext->width, m_pCodecContext->height);
- BYTE* buffer = new BYTE[numBytes];
-
- // Assign appropriate parts of buffer to image planes in pFrameRGB
- m_dllAvCodec.avpicture_fill((AVPicture *)m_pConvertFrame, buffer, PIX_FMT_YUV420P, m_pCodecContext->width, m_pCodecContext->height);
+ m_pConvertFrame = (AVPicture*)m_dllAvUtil.av_mallocz(sizeof(AVPicture));
+ // Due to a bug in swsscale we need to allocate one extra line of data
+ if(m_dllAvCodec.avpicture_alloc( m_pConvertFrame
+ , PIX_FMT_YUV420P
+ , m_pCodecContext->width
+ , m_pCodecContext->height+1) < 0)
+ {
+ m_dllAvUtil.av_free(m_pConvertFrame);
+ m_pConvertFrame = NULL;
+ return VC_ERROR;
+ }
}
// convert the picture
struct SwsContext *context = m_dllSwScale.sws_getContext(m_pCodecContext->width, m_pCodecContext->height,
m_pCodecContext->pix_fmt, m_pCodecContext->width, m_pCodecContext->height,
PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
- uint8_t *src[] = { m_pFrame->data[0], m_pFrame->data[1], m_pFrame->data[2] };
- int srcStride[] = { m_pFrame->linesize[0], m_pFrame->linesize[1], m_pFrame->linesize[2] };
- uint8_t *dst[] = { m_pConvertFrame->data[0], m_pConvertFrame->data[1], m_pConvertFrame->data[2] };
- int dstStride[] = { m_pConvertFrame->linesize[0], m_pConvertFrame->linesize[1], m_pConvertFrame->linesize[2] };
- m_dllSwScale.sws_scale(context, src, srcStride, 0, m_pCodecContext->height, dst, dstStride);
+ m_dllSwScale.sws_scale(context
+ , m_pFrame->data
+ , m_pFrame->linesize
+ , 0
+ , m_pCodecContext->height
+ , m_pConvertFrame->data
+ , m_pConvertFrame->linesize);
m_dllSwScale.sws_freeContext(context);
-
- m_pConvertFrame->coded_picture_number = m_pFrame->coded_picture_number;
- m_pConvertFrame->interlaced_frame = m_pFrame->interlaced_frame;
- m_pConvertFrame->repeat_pict = m_pFrame->repeat_pict;
- m_pConvertFrame->top_field_first = m_pFrame->top_field_first;
- m_pConvertFrame->reordered_opaque = m_pFrame->reordered_opaque;
}
else
{
// no need to convert, just free any existing convert buffers
if (m_pConvertFrame)
{
- delete[] m_pConvertFrame->data[0];
+ m_dllAvCodec.avpicture_free(m_pConvertFrame);
m_dllAvUtil.av_free(m_pConvertFrame);
m_pConvertFrame = NULL;
}
@@ -329,18 +327,30 @@ bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture)
pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
// if we have a converted frame, use that
- AVFrame *frame = m_pConvertFrame ? m_pConvertFrame : m_pFrame;
+ AVFrame *frame = m_pFrame;
if (!frame)
return false;
-
- for (int i = 0; i < 4; i++) pDvdVideoPicture->data[i] = frame->data[i];
- for (int i = 0; i < 4; i++) pDvdVideoPicture->iLineSize[i] = frame->linesize[i];
+
+ if(m_pConvertFrame)
+ {
+ for (int i = 0; i < 4; i++)
+ pDvdVideoPicture->data[i] = m_pConvertFrame->data[i];
+ for (int i = 0; i < 4; i++)
+ pDvdVideoPicture->iLineSize[i] = m_pConvertFrame->linesize[i];
+ }
+ else
+ {
+ for (int i = 0; i < 4; i++)
+ pDvdVideoPicture->data[i] = frame->data[i];
+ for (int i = 0; i < 4; i++)
+ pDvdVideoPicture->iLineSize[i] = frame->linesize[i];
+ }
pDvdVideoPicture->iRepeatPicture = frame->repeat_pict;
pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
pDvdVideoPicture->iFlags |= frame->interlaced_frame ? DVP_FLAG_INTERLACED : 0;
pDvdVideoPicture->iFlags |= frame->top_field_first ? DVP_FLAG_TOP_FIELD_FIRST: 0;
- pDvdVideoPicture->iFlags |= frame->data[0] ? 0 : DVP_FLAG_DROPPED;
+ pDvdVideoPicture->iFlags |= pDvdVideoPicture->data[0] ? 0 : DVP_FLAG_DROPPED;
if(m_pCodecContext->pix_fmt == PIX_FMT_YUVJ420P)
pDvdVideoPicture->color_range = 1;
@@ -48,7 +48,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
AVFrame* m_pFrame;
AVCodecContext* m_pCodecContext;
- AVFrame* m_pConvertFrame;
+ AVPicture* m_pConvertFrame;
int m_iPictureWidth;
int m_iPictureHeight;

0 comments on commit 8131ed8

Please sign in to comment.