Skip to content

Commit

Permalink
[aml] changed, track width, height and frame rate as well as aspect r…
Browse files Browse the repository at this point in the history
…ation for mpeg2 video content
  • Loading branch information
davilla committed Mar 19, 2013
1 parent 423cf14 commit 1fe026d
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 42 deletions.
54 changes: 35 additions & 19 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() :
m_queue_depth(0),
m_framerate(0.0),
m_video_rate(0),
m_mpeg2_aspect(NULL)
m_mpeg2_sequence(NULL)
{
pthread_mutex_init(&m_queue_mutex, NULL);
}
Expand All @@ -67,9 +67,17 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option
case CODEC_ID_MPEG1VIDEO:
case CODEC_ID_MPEG2VIDEO:
case CODEC_ID_MPEG2VIDEO_XVMC:
m_mpeg2_aspect_pts = 0;
m_mpeg2_aspect = new mpeg2_aspect;
m_mpeg2_aspect->ratio = hints.aspect;
m_mpeg2_sequence_pts = 0;
m_mpeg2_sequence = new mpeg2_sequence;
m_mpeg2_sequence->width = hints.width;
m_mpeg2_sequence->height = hints.height;
m_mpeg2_sequence->ratio = hints.aspect;
if (hints.rfpsrate > 0 && hints.rfpsscale != 0)
m_mpeg2_sequence->rate = (float)hints.rfpsrate / hints.rfpsscale;
else if (hints.fpsrate > 0 && hints.fpsscale != 0)
m_mpeg2_sequence->rate = (float)hints.fpsrate / hints.fpsscale;
else
m_mpeg2_sequence->rate = 1.0;
m_pFormatName = "am-mpeg2";
break;
case CODEC_ID_H264:
Expand Down Expand Up @@ -171,8 +179,8 @@ void CDVDVideoCodecAmlogic::Dispose(void)
m_Codec->CloseDecoder(), m_Codec = NULL;
if (m_videobuffer.iFlags)
m_videobuffer.iFlags = 0;
if (m_mpeg2_aspect)
delete m_mpeg2_aspect, m_mpeg2_aspect = NULL;
if (m_mpeg2_sequence)
delete m_mpeg2_sequence, m_mpeg2_sequence = NULL;

while (m_queue_depth)
FrameQueuePop();
Expand Down Expand Up @@ -208,7 +216,7 @@ void CDVDVideoCodecAmlogic::Reset(void)
FrameQueuePop();

m_Codec->Reset();
m_mpeg2_aspect_pts = 0;
m_mpeg2_sequence_pts = 0;
}

bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture)
Expand All @@ -218,8 +226,8 @@ bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture)
*pDvdVideoPicture = m_videobuffer;

// check for mpeg2 aspect ratio changes
if (m_mpeg2_aspect && pDvdVideoPicture->pts >= m_mpeg2_aspect_pts)
m_aspect_ratio = m_mpeg2_aspect->ratio;
if (m_mpeg2_sequence && pDvdVideoPicture->pts >= m_mpeg2_sequence_pts)
m_aspect_ratio = m_mpeg2_sequence->ratio;

pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth;
pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight;
Expand Down Expand Up @@ -326,21 +334,29 @@ void CDVDVideoCodecAmlogic::FrameQueuePush(double dts, double pts)

void CDVDVideoCodecAmlogic::FrameRateTracking(BYTE *pData, int iSize, double dts, double pts)
{
FrameQueuePush(dts, pts);

if (m_mpeg2_aspect)
// mpeg2 handling
if (m_mpeg2_sequence)
{
// if mpeg2, probe demux data for aspect_ratio_information
// in the sequence_header_code.
if (CBitstreamConverter::mpeg2_aspect_ratio_information(pData, iSize, m_mpeg2_aspect))
// probe demux for sequence_header_code NAL and
// decode aspect ratio and frame rate.
if (CBitstreamConverter::mpeg2_sequence_header(pData, iSize, m_mpeg2_sequence))
{
m_mpeg2_aspect_pts = pts;
if (m_mpeg2_aspect_pts == DVD_NOPTS_VALUE)
m_mpeg2_aspect_pts = dts;
CLog::Log(LOGDEBUG, "%s: detected new aspect ratio(%f)", __MODULE_NAME__, m_mpeg2_aspect->ratio);
m_mpeg2_sequence_pts = pts;
if (m_mpeg2_sequence_pts == DVD_NOPTS_VALUE)
m_mpeg2_sequence_pts = dts;

m_framerate = m_mpeg2_sequence->rate;
m_video_rate = (int)(0.5 + (96000.0 / m_framerate));

CLog::Log(LOGDEBUG, "%s: detected mpeg2 aspect ratio(%f), framerate(%f), video_rate(%d)",
__MODULE_NAME__, m_mpeg2_sequence->ratio, m_framerate, m_video_rate);
}
return;
}

// everything else
FrameQueuePush(dts, pts);

// we might have out-of-order pts,
// so make sure we wait for at least 8 values in sorted queue.
if (m_queue_depth > 16)
Expand Down
6 changes: 3 additions & 3 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

class CAMLCodec;
struct frame_queue;
struct mpeg2_aspect;
struct mpeg2_sequence;

class CDVDVideoCodecAmlogic : public CDVDVideoCodec
{
Expand Down Expand Up @@ -62,6 +62,6 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec
double m_framerate;
int m_video_rate;
float m_aspect_ratio;
mpeg2_aspect *m_mpeg2_aspect;
double m_mpeg2_aspect_pts;
mpeg2_sequence *m_mpeg2_sequence;
double m_mpeg2_sequence_pts;
};
95 changes: 80 additions & 15 deletions xbmc/utils/BitstreamConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ int CBitstreamConverter::nal_bs_read_ue(nal_bitstream *bs)
return ((1 << i) - 1 + nal_bs_read(bs, i));
}

bool CBitstreamConverter::mpeg2_aspect_ratio_information(const uint8_t *data, const uint32_t size, mpeg2_aspect *aspect)
bool CBitstreamConverter::mpeg2_sequence_header(const uint8_t *data, const uint32_t size, mpeg2_sequence *sequence)
{
// parse nal's until a sequence_header_code is found
// and return the aspect_ratio_information if changed.
// and return the width, height, aspect ratio and frame rate if changed.
bool changed = false;

if (!data)
Expand All @@ -194,36 +194,101 @@ bool CBitstreamConverter::mpeg2_aspect_ratio_information(const uint8_t *data, co
nal_end = avc_find_startcode(nal_start, end);
if (*nal_start == 0xB3)
{
float ratio;
// nal_start == sequence_header_code
nal_bitstream bs;
nal_bs_init(&bs, nal_start, end - nal_start);

// sequence_header_code
nal_bs_read(&bs, 8);

// width
// nal_start + 12 bits == horizontal_size_value
uint32_t width = nal_bs_read(&bs, 12);
if (width != sequence->width)
{
changed = true;
sequence->width = width;
}
// height
// nal_start + 24 bits == vertical_size_value
uint32_t height = nal_bs_read(&bs, 12);
if (height != sequence->height)
{
changed = true;
sequence->height = height;
}

// aspect ratio
// nal_start + 28 bits == aspect_ratio_information
// nal_start + 32 bits == frame_rate_code
// so nal_start + 4 bytes >> 4 bits == aspect_ratio_information
const uint8_t aspect_ratio_information = *(nal_start + 4) & 0xF0;
switch(aspect_ratio_information)
float ratio = sequence->ratio;
uint32_t ratio_info = nal_bs_read(&bs, 4);
switch(ratio_info)
{
case 0x10:
case 0x01:
ratio = 1.0;
break;
default:
case 0x20:
case 0x02:
ratio = 4.0/3.0;
break;
case 0x30:
case 0x03:
ratio = 16.0/9.0;
break;
case 0x40:
case 0x04:
ratio = 2.21;
break;
}
if (aspect_ratio_information != aspect->ratio_info)
if (ratio_info != sequence->ratio_info)
{
changed = true;
sequence->ratio = ratio;
sequence->ratio_info = ratio_info;
}

// frame rate
// nal_start + 32 bits == frame_rate_code
float rate = sequence->rate;
uint32_t rate_info = nal_bs_read(&bs, 4);
switch(rate_info)
{
default:
case 0x01:
rate = 24000.0 / 1001.0;
break;
case 0x02:
rate = 24000.0 / 1000.0;
break;
case 0x03:
rate = 25000.0 / 1000.0;
break;
case 0x04:
rate = 30000.0 / 1001.0;
break;
case 0x05:
rate = 30000.0 / 1000.0;
break;
case 0x06:
rate = 50000.0 / 1000.0;
break;
case 0x07:
rate = 60000.0 / 1001.0;
break;
case 0x08:
rate = 60000.0 / 1000.0;
break;
}
if (rate_info != sequence->rate_info)
{
changed = true;
aspect->ratio = ratio;
aspect->ratio_info = aspect_ratio_information;
sequence->rate = rate;
sequence->rate_info = rate_info;
}
/*
if (changed)
{
CLog::Log(LOGDEBUG, "CBitstreamConverter::mpeg2_sequence_header: "
"width(%d), height(%d), ratio(%f), rate(%f)", width, height, ratio, rate);
}
*/
}
nal_start = nal_end;
}
Expand Down
14 changes: 9 additions & 5 deletions xbmc/utils/BitstreamConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,15 @@ typedef struct
uint64_t cache;
} nal_bitstream;

typedef struct mpeg2_aspect
typedef struct mpeg2_sequence
{
float ratio;
int ratio_info;
} mpeg2_aspect;
uint32_t width;
uint32_t height;
float rate;
uint32_t rate_info;
float ratio;
uint32_t ratio_info;
} mpeg2_sequence;

typedef struct
{
Expand Down Expand Up @@ -130,7 +134,7 @@ class CBitstreamConverter
int GetExtraSize();

static void parseh264_sps(const uint8_t *sps, const uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames);
static bool mpeg2_aspect_ratio_information(const uint8_t *data, const uint32_t size, mpeg2_aspect *aspect);
static bool mpeg2_sequence_header(const uint8_t *data, const uint32_t size, mpeg2_sequence *sequence);
protected:
// bytestream (Annex B) to bistream conversion support.
static void nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size);
Expand Down

2 comments on commit 1fe026d

@Memphiz
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for me? ^^

@davilla
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe, almost. it's not hooked yet.

Please sign in to comment.