Skip to content

Commit

Permalink
Change VideoFrameH264 to bool type and clean implementation.
Browse files Browse the repository at this point in the history
This is so we can signal an error in processing a video frame, if necessary. This also cleans up the configuration of the H264 decoder by adding it into the main Configuration function, as well as removing unneccesary functions and lines.
  • Loading branch information
acmiyaguchi committed Aug 11, 2015
1 parent e8a4a12 commit 54fda86
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 66 deletions.
7 changes: 7 additions & 0 deletions addons/library.kodi.game/libKODI_game.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class CHelper_libKODI_game
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_unregister_me)) throw false;
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_close_game)) throw false;
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_video_frame)) throw false;
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_video_frame_h264)) throw false;
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_audio_frames)) throw false;
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_hw_set_info)) throw false;
if (!GAME_REGISTER_SYMBOL(m_libKODI_game, GAME_hw_get_current_framebuffer)) throw false;
Expand Down Expand Up @@ -134,6 +135,11 @@ class CHelper_libKODI_game
return GAME_video_frame(m_handle, m_callbacks, data, width, height, format);
}

bool VideoFrameH264(const uint8_t* data, int size, unsigned int width, unsigned int height)
{
return GAME_video_frame_h264(m_handle, m_callbacks, data, size, width, height);
}

void AudioFrames(const uint8_t* data, unsigned int frames, GAME_AUDIO_FORMAT format)
{
return GAME_audio_frames(m_handle, m_callbacks, data, frames, format);
Expand Down Expand Up @@ -209,6 +215,7 @@ class CHelper_libKODI_game
void (*GAME_unregister_me)(void* handle, CB_GameLib* cb);
void (*GAME_close_game)(void* handle, CB_GameLib* cb);
void (*GAME_video_frame)(void* handle, CB_GameLib* cb, const uint8_t*, unsigned int, unsigned int, GAME_RENDER_FORMAT);
bool (*GAME_video_frame_h264)(void* handle, CB_GameLib* cb, const uint8_t*, int, unsigned int, unsigned int);
void (*GAME_audio_frames)(void* handle, CB_GameLib* cb, const uint8_t*, unsigned int, GAME_AUDIO_FORMAT);
void (*GAME_hw_set_info)(void* handle, CB_GameLib* cb, const struct game_hw_info*);
uintptr_t (*GAME_hw_get_current_framebuffer)(void* handle, CB_GameLib* cb);
Expand Down
7 changes: 7 additions & 0 deletions lib/addons/library.kodi.game/libKODI_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ DLLEXPORT void GAME_video_frame(AddonCB* frontend, CB_GameLib* cb, const uint8_t
return cb->VideoFrame(frontend->addonData, data, width, height, format);
}

DLLEXPORT void GAME_video_frame_h264(AddonCB* frontend, CB_GameLib* cb, const uint8_t* data, int size, unsigned int width, unsigned int height)
{
if (frontend == NULL || cb == NULL)
return;
return cb->VideoFrameH264(frontend->addonData, data, size, width, height);
}

DLLEXPORT void GAME_audio_frames(AddonCB* frontend, CB_GameLib* cb, const uint8_t* data, unsigned int frames, GAME_AUDIO_FORMAT format)
{
if (frontend == NULL || cb == NULL)
Expand Down
7 changes: 4 additions & 3 deletions xbmc/addons/AddonCallbacksGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ CAddonCallbacksGame::CAddonCallbacksGame(CAddon* addon)
/* write XBMC game specific add-on function addresses to callback table */
m_callbacks->CloseGame = CloseGame;
m_callbacks->VideoFrame = VideoFrame;
m_callbacks->VideoFrameH264 = VideoFrameH264;
m_callbacks->AudioFrames = AudioFrames;
m_callbacks->HwSetInfo = HwSetInfo;
m_callbacks->HwGetCurrentFramebuffer = HwGetCurrentFramebuffer;
Expand Down Expand Up @@ -140,13 +141,13 @@ void CAddonCallbacksGame::VideoFrame(void* addonData, const uint8_t* data, unsig
}


void CAddonCallbacksGame::VideoFrameH264(void* addonData, const uint8_t* data, int size, unsigned int width, unsigned int height)
bool CAddonCallbacksGame::VideoFrameH264(void* addonData, const uint8_t* data, int size, unsigned int width, unsigned int height)
{
CRetroPlayer* retroPlayer = GetRetroPlayer(addonData, __FUNCTION__);
if (!retroPlayer)
return;
return false;

retroPlayer->VideoFrameH264(width, height, data, size);
return retroPlayer->VideoFrameH264(width, height, data, size);
}

void CAddonCallbacksGame::AudioFrames(void* addonData, const uint8_t* data, unsigned int frames, GAME_AUDIO_FORMAT format)
Expand Down
2 changes: 1 addition & 1 deletion xbmc/addons/AddonCallbacksGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class CAddonCallbacksGame

static void CloseGame(void* addonData);
static void VideoFrame(void* addonData, const uint8_t* data, unsigned int width, unsigned int height, GAME_RENDER_FORMAT format);
static void VideoFrameH264(void* addonData, const uint8_t* data, int size, unsigned int width, unsigned int height);
static bool VideoFrameH264(void* addonData, const uint8_t* data, int size, unsigned int width, unsigned int height);
static void AudioFrames(void* addonData, const uint8_t* data, unsigned int frames, GAME_AUDIO_FORMAT format);
static void HwSetInfo(void* addonData, const game_hw_info* hw_info);
static uintptr_t HwGetCurrentFramebuffer(void* addonData);
Expand Down
2 changes: 1 addition & 1 deletion xbmc/addons/include/kodi_game_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ typedef struct CB_GameLib
* \param data The frame's data
* \param size The frame's size
*/
void (*VideoFrameH264)(void* addonData, const uint8_t* data, int size, unsigned int width, unsigned int height);
bool (*VideoFrameH264)(void* addonData, const uint8_t* data, int size, unsigned int width, unsigned int height);

/*!
* \brief Render a chunk of audio data
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/RetroPlayer/RetroPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class CRetroPlayer : public IPlayer, protected CThread

// Game API
void VideoFrame(AVPixelFormat format, unsigned int width, unsigned int height, const uint8_t* data) { m_video.VideoFrame(format, width, height, data); }
void VideoFrameH264(unsigned int width, unsigned int height, const uint8_t* data, int size) { m_video.VideoFrameH264(width, height, data, size); }
bool VideoFrameH264(unsigned int width, unsigned int height, const uint8_t* data, int size) { return m_video.VideoFrameH264(width, height, data, size); }
void AudioFrames(AEDataFormat format, unsigned int frames, const uint8_t* data) { m_audio.AudioFrames(format, frames, data); }
protected:
virtual void Process();
Expand Down
102 changes: 46 additions & 56 deletions xbmc/cores/RetroPlayer/RetroPlayerVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,6 @@ void CRetroPlayerVideo::Cleanup(void)
av_frame_free(&m_frame);
m_frame = NULL;
}

if (m_h264_swsContext) {
sws_freeContext(m_h264_swsContext);
m_h264_swsContext = NULL;
}
}

void CRetroPlayerVideo::Start(double framerate)
Expand Down Expand Up @@ -121,25 +116,27 @@ bool CRetroPlayerVideo::VideoFrameH264(unsigned int width, unsigned int height,
int got_picture_ptr = 0;
int len = 0;

if (!m_codec_context) {
SetupDecoder(width, height);
}

if (!m_bStop && !IsFrameReady()) {
av_init_packet(&packet);
packet.data = const_cast<uint8_t*>(data);
packet.size = size;

len = avcodec_decode_video2(m_codec_context, m_frame, &got_picture_ptr, &packet);
if (len < 0) {
CLog::Log(LOGERROR, "RetroPlayerVideo: Error while decoding frame");
return false;
if (Configure(PIX_FMT_YUV420P, width, height, true))
{
av_init_packet(&packet);
packet.data = const_cast<uint8_t*>(data);
packet.size = size;

len = avcodec_decode_video2(m_codec_context, m_frame, &got_picture_ptr, &packet);
if (len < 0) {
CLog::Log(LOGERROR, "RetroPlayerVideo: Error while decoding frame");
return false;
}
if (got_picture_ptr) {
sws_scale(m_swsContext, m_frame->data, m_frame->linesize, 0, m_frame->height, m_picture->data, m_picture->iLineSize);
SetFrameReady(true);
return true;
}
}
if (got_picture_ptr) {
sws_scale(m_h264_swsContext, m_frame->data, m_frame->linesize, 0,
m_frame->height, m_picture->data, m_picture->iLineSize);
SetFrameReady(true);
return true;
else
{
Stop();
}
}

Expand Down Expand Up @@ -182,17 +179,18 @@ void CRetroPlayerVideo::Process(void)
Cleanup();
}

bool CRetroPlayerVideo::Configure(AVPixelFormat format, unsigned int width, unsigned int height)
bool CRetroPlayerVideo::Configure(AVPixelFormat format, unsigned int width, unsigned int height, bool setupH264)
{
// Check for valid format (TODO)
if (GetPitch(format, width) == 0)
if (!setupH264 && GetPitch(format, width) == 0)
return false;

if (!g_renderManager.IsConfigured() ||
m_format != format ||
m_picture == NULL ||
m_picture->iWidth != width ||
m_picture->iHeight != height)
m_picture->iHeight != height ||
(setupH264 && m_codec == NULL))
{
// Determine RenderManager flags
unsigned int flags = CONF_FLAGS_YUVCOEF_BT601 | // color_matrix = 4
Expand All @@ -211,10 +209,30 @@ bool CRetroPlayerVideo::Configure(AVPixelFormat format, unsigned int width, unsi

Cleanup();

if(setupH264) {
m_codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!m_codec) {
CLog::Log(LOGERROR, "RetroPlayerVideo: Unable to find H264 codec");
return false;
}

m_codec_context = avcodec_alloc_context3(m_codec);
if (m_codec->capabilities & CODEC_CAP_TRUNCATED) {
m_codec_context->flags |= CODEC_FLAG_TRUNCATED;
}

if (avcodec_open2(m_codec_context, m_codec, NULL) < 0) {
CLog::Log(LOGERROR, "RetroPlayerVideo: Unable to open codec context.");
return false;
}

m_frame = av_frame_alloc();
}

m_swsContext = sws_getContext(width, height, format,
width, height, PIX_FMT_YUV420P,
SWS_FAST_BILINEAR | SwScaleCPUFlags(),
NULL, NULL, NULL);
width, height, PIX_FMT_YUV420P,
SWS_FAST_BILINEAR | SwScaleCPUFlags(),
NULL, NULL, NULL);

m_picture = CDVDCodecUtils::AllocatePicture(width, height);

Expand Down Expand Up @@ -263,34 +281,6 @@ void CRetroPlayerVideo::SetFrameReady(bool bReady)
m_frameReadyEvent.Set();
}

bool CRetroPlayerVideo::SetupDecoder(int width, int height)
{
m_codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!m_codec) {
CLog::Log(LOGERROR, "RetroPlayerVideo: Unable to find H264 codec");
return false;
}

m_codec_context = avcodec_alloc_context3(m_codec);
if (m_codec->capabilities & CODEC_CAP_TRUNCATED) {
m_codec_context->flags |= CODEC_FLAG_TRUNCATED;
}

if (avcodec_open2(m_codec_context, m_codec, NULL) < 0) {
CLog::Log(LOGERROR, "RetroPlayerVideo: Unable to open codec context.");
return false;
}

m_h264_swsContext = sws_getContext(width, height, PIX_FMT_YUV420P,
width, height, PIX_FMT_YUV420P,
SWS_FAST_BILINEAR | SwScaleCPUFlags(),
NULL, NULL, NULL);

m_frame = av_frame_alloc();

return true;
}

unsigned int CRetroPlayerVideo::GetPitch(AVPixelFormat format, unsigned int width)
{
unsigned int pitch = 0;
Expand Down
5 changes: 1 addition & 4 deletions xbmc/cores/RetroPlayer/RetroPlayerVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,13 @@ class CRetroPlayerVideo : protected CThread
private:
void Cleanup(void);

bool Configure(AVPixelFormat format, unsigned int width, unsigned int height);
bool Configure(AVPixelFormat format, unsigned int width, unsigned int height, bool setupH264=false);

void ColorspaceConversion(AVPixelFormat format, unsigned int width, unsigned int height, const uint8_t* data, DVDVideoPicture &output);

bool IsFrameReady(void);
void SetFrameReady(bool bReady);

bool SetupDecoder(int width, int height);

static unsigned int GetPitch(AVPixelFormat format, unsigned int width);

double m_framerate;
Expand All @@ -71,5 +69,4 @@ class CRetroPlayerVideo : protected CThread
AVCodec* m_codec;
AVCodecContext* m_codec_context;
AVFrame* m_frame;
SwsContext* m_h264_swsContext;
};

0 comments on commit 54fda86

Please sign in to comment.