2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
27 #if defined(HAVE_LIBOPENMAX)
29 #include "settings/GUISettings.h"
30 #include "DVDStreamInfo.h"
31 #include "DVDVideoCodecOpenMax.h"
32 #include "OpenMaxVideo.h"
33 #include "utils/log.h"
35 #define CLASSNAME "COpenMax"
36 ////////////////////////////////////////////////////////////////////////////////////////////
37 ////////////////////////////////////////////////////////////////////////////////////////////
38 CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() : CDVDVideoCodec()
41 m_pFormatName = "omx-xxxx";
43 m_convert_bitstream = false;
44 memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
47 CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax()
52 bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
54 // we always qualify even if DVDFactoryCodec does this too.
55 if (g_guiSettings.GetBool("videoplayer.useomx") && !hints.software)
57 m_convert_bitstream = false;
63 m_pFormatName = "omx-h264";
64 if (hints.extrasize < 7 || hints.extradata == NULL)
67 "%s::%s - avcC data too small or missing", CLASSNAME, __func__);
70 // valid avcC data (bitstream) always starts with the value 1 (version)
71 if ( *(char*)hints.extradata == 1 )
72 m_convert_bitstream = bitstream_convert_init(hints.extradata, hints.extrasize);
76 m_pFormatName = "omx-mpeg4";
78 case CODEC_ID_MPEG2VIDEO:
79 m_pFormatName = "omx-mpeg2";
82 m_pFormatName = "omx-vc1";
89 m_omx_decoder = new COpenMaxVideo;
90 if (!m_omx_decoder->Open(hints))
93 "%s::%s - failed to open, codec(%d), profile(%d), level(%d)",
94 CLASSNAME, __func__, hints.codec, hints.profile, hints.level);
98 // allocate a YV12 DVDVideoPicture buffer.
99 // first make sure all properties are reset.
100 memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
101 unsigned int luma_pixels = hints.width * hints.height;
102 unsigned int chroma_pixels = luma_pixels/4;
104 m_videobuffer.dts = DVD_NOPTS_VALUE;
105 m_videobuffer.pts = DVD_NOPTS_VALUE;
106 //m_videobuffer.format = RENDER_FMT_YUV420P;
107 m_videobuffer.format = RENDER_FMT_OMXEGL;
108 m_videobuffer.color_range = 0;
109 m_videobuffer.color_matrix = 4;
110 m_videobuffer.iFlags = DVP_FLAG_ALLOCATED;
111 m_videobuffer.iWidth = hints.width;
112 m_videobuffer.iHeight = hints.height;
113 m_videobuffer.iDisplayWidth = hints.width;
114 m_videobuffer.iDisplayHeight = hints.height;
122 void CDVDVideoCodecOpenMax::Dispose()
126 m_omx_decoder->Close();
127 delete m_omx_decoder;
128 m_omx_decoder = NULL;
130 if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED)
132 m_videobuffer.iFlags = 0;
134 if (m_convert_bitstream)
136 if (m_sps_pps_context.sps_pps_data)
138 free(m_sps_pps_context.sps_pps_data);
139 m_sps_pps_context.sps_pps_data = NULL;
144 void CDVDVideoCodecOpenMax::SetDropState(bool bDrop)
146 m_omx_decoder->SetDropState(bDrop);
149 int CDVDVideoCodecOpenMax::Decode(BYTE* pData, int iSize, double dts, double pts)
154 int demuxer_bytes = iSize;
155 uint8_t *demuxer_content = pData;
156 bool bitstream_convered = false;
158 if (m_convert_bitstream)
160 // convert demuxer packet from bitstream to bytestream (AnnexB)
161 int bytestream_size = 0;
162 uint8_t *bytestream_buff = NULL;
164 bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size);
165 if (bytestream_buff && (bytestream_size > 0))
167 bitstream_convered = true;
168 demuxer_bytes = bytestream_size;
169 demuxer_content = bytestream_buff;
173 rtn = m_omx_decoder->Decode(demuxer_content, demuxer_bytes, dts, pts);
175 if (bitstream_convered)
176 free(demuxer_content);
184 void CDVDVideoCodecOpenMax::Reset(void)
186 m_omx_decoder->Reset();
189 bool CDVDVideoCodecOpenMax::GetPicture(DVDVideoPicture* pDvdVideoPicture)
191 m_omx_decoder->GetPicture(&m_videobuffer);
192 *pDvdVideoPicture = m_videobuffer;
194 return VC_PICTURE | VC_BUFFER;
197 ////////////////////////////////////////////////////////////////////////////////////////////
198 bool CDVDVideoCodecOpenMax::bitstream_convert_init(void *in_extradata, int in_extrasize)
200 // based on h264_mp4toannexb_bsf.c (ffmpeg)
201 // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
202 // and Licensed GPL 2.1 or greater
205 m_sps_pps_context.sps_pps_data = NULL;
208 if (!in_extradata || in_extrasize < 6)
212 uint32_t total_size = 0;
213 uint8_t *out = NULL, unit_nb, sps_done = 0;
214 const uint8_t *extradata = (uint8_t*)in_extradata + 4;
215 static const uint8_t nalu_header[4] = {0, 0, 0, 1};
217 // retrieve length coded size
218 m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1;
219 if (m_sps_pps_context.length_size == 3)
222 // retrieve sps and pps unit(s)
223 unit_nb = *extradata++ & 0x1f; // number of sps unit(s)
226 unit_nb = *extradata++; // number of pps unit(s)
231 unit_size = extradata[0] << 8 | extradata[1];
232 total_size += unit_size + 4;
233 if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) )
238 out = (uint8_t*)realloc(out, total_size);
242 memcpy(out + total_size - unit_size - 4, nalu_header, 4);
243 memcpy(out + total_size - unit_size, extradata + 2, unit_size);
244 extradata += 2 + unit_size;
246 if (!unit_nb && !sps_done++)
247 unit_nb = *extradata++; // number of pps unit(s)
250 m_sps_pps_context.sps_pps_data = out;
251 m_sps_pps_context.size = total_size;
252 m_sps_pps_context.first_idr = 1;
257 bool CDVDVideoCodecOpenMax::bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size)
259 // based on h264_mp4toannexb_bsf.c (ffmpeg)
260 // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
261 // and Licensed GPL 2.1 or greater
263 uint8_t *buf = pData;
264 uint32_t buf_size = iSize;
267 uint32_t cumul_size = 0;
268 const uint8_t *buf_end = buf + buf_size;
272 if (buf + m_sps_pps_context.length_size > buf_end)
275 if (m_sps_pps_context.length_size == 1)
277 else if (m_sps_pps_context.length_size == 2)
278 nal_size = buf[0] << 8 | buf[1];
280 nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
282 buf += m_sps_pps_context.length_size;
283 unit_type = *buf & 0x1f;
285 if (buf + nal_size > buf_end || nal_size < 0)
288 // prepend only to the first type 5 NAL unit of an IDR picture
289 if (m_sps_pps_context.first_idr && unit_type == 5)
291 bitstream_alloc_and_copy(poutbuf, poutbuf_size,
292 m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size);
293 m_sps_pps_context.first_idr = 0;
297 bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size);
298 if (!m_sps_pps_context.first_idr && unit_type == 1)
299 m_sps_pps_context.first_idr = 1;
303 cumul_size += nal_size + m_sps_pps_context.length_size;
304 } while (cumul_size < buf_size);
315 void CDVDVideoCodecOpenMax::bitstream_alloc_and_copy(
316 uint8_t **poutbuf, int *poutbuf_size,
317 const uint8_t *sps_pps, uint32_t sps_pps_size,
318 const uint8_t *in, uint32_t in_size)
320 // based on h264_mp4toannexb_bsf.c (ffmpeg)
321 // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
322 // and Licensed GPL 2.1 or greater
324 #define CHD_WB32(p, d) { \
325 ((uint8_t*)(p))[3] = (d); \
326 ((uint8_t*)(p))[2] = (d) >> 8; \
327 ((uint8_t*)(p))[1] = (d) >> 16; \
328 ((uint8_t*)(p))[0] = (d) >> 24; }
330 uint32_t offset = *poutbuf_size;
331 uint8_t nal_header_size = offset ? 3 : 4;
333 *poutbuf_size += sps_pps_size + in_size + nal_header_size;
334 *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size);
336 memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
338 memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
341 CHD_WB32(*poutbuf + sps_pps_size, 1);
345 (*poutbuf + offset + sps_pps_size)[0] = 0;
346 (*poutbuf + offset + sps_pps_size)[1] = 0;
347 (*poutbuf + offset + sps_pps_size)[2] = 1;