TEST(TestEndianSwap, Endian_SwapLE32) { uint32_t ref, var; ref = 0x00FF00FF; var = Endian_SwapLE32(0x00FF00FF); EXPECT_EQ(ref, var); }
static bool ReadUInt32(FILE* file, uint32_t& value) { if (file == nullptr) return false; if (fread(&value, sizeof(uint32_t), 1, file) != 1) return false; value = Endian_SwapLE32(value); return true; }
CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() { if(m_SubtitleIndex<0) return NULL; if(m_Subtitle.num_rects == 0 && m_SubtitleIndex == 0) { // we must add an empty overlay to replace the previous one CDVDOverlay* o = new CDVDOverlay(DVDOVERLAY_TYPE_NONE); o->iPTSStartTime = m_StartTime; o->iPTSStopTime = 0; o->replace = true; m_SubtitleIndex++; return o; } if(m_Subtitle.format == 0) { if(m_SubtitleIndex >= (int)m_Subtitle.num_rects) return NULL; if(m_Subtitle.rects[m_SubtitleIndex] == NULL) return NULL; AVSubtitleRect& rect = *m_Subtitle.rects[m_SubtitleIndex]; if (rect.pict.data[0] == NULL) return NULL; CDVDOverlayImage* overlay = new CDVDOverlayImage(); overlay->iPTSStartTime = m_StartTime; overlay->iPTSStopTime = m_StopTime; overlay->replace = true; overlay->linesize = rect.w; overlay->data = (uint8_t*)malloc(rect.w * rect.h); overlay->palette = (uint32_t*)malloc(rect.nb_colors*4); overlay->palette_colors = rect.nb_colors; overlay->x = rect.x; overlay->y = rect.y; overlay->width = rect.w; overlay->height = rect.h; overlay->bForced = rect.flags != 0; int right = overlay->x + overlay->width; int bottom = overlay->y + overlay->height; if(m_height == 0 && m_pCodecContext->height) m_height = m_pCodecContext->height; if(m_width == 0 && m_pCodecContext->width) m_width = m_pCodecContext->width; if(bottom > m_height) { if (bottom <= 480) m_height = 480; else if(bottom <= 576) m_height = 576; else if(bottom <= 720) m_height = 720; else if(bottom <= 1080) m_height = 1080; else m_height = bottom; } if(right > m_width) { if (right <= 720) m_width = 720; else if(right <= 1024) m_width = 1024; else if(right <= 1280) m_width = 1280; else if(right <= 1920) m_width = 1920; else m_width = right; } overlay->source_width = m_width; overlay->source_height = m_height; uint8_t* s = rect.pict.data[0]; uint8_t* t = overlay->data; for(int i=0;i<rect.h;i++) { memcpy(t, s, rect.w); s += rect.pict.linesize[0]; t += overlay->linesize; } for(int i=0;i<rect.nb_colors;i++) overlay->palette[i] = Endian_SwapLE32(((uint32_t *)rect.pict.data[1])[i]); av_free(rect.pict.data[0]); av_free(rect.pict.data[1]); av_freep(&m_Subtitle.rects[m_SubtitleIndex]); m_SubtitleIndex++; return overlay; } return NULL; }
CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() { if(m_SubtitleIndex<0) return NULL; if(m_Subtitle.num_rects == 0 && m_SubtitleIndex == 0) { // we must add an empty overlay to replace the previous one CDVDOverlay* o = new CDVDOverlay(DVDOVERLAY_TYPE_NONE); o->iPTSStartTime = m_StartTime; o->iPTSStopTime = 0; o->replace = true; m_SubtitleIndex++; return o; } if(m_Subtitle.format == 0) { if(m_SubtitleIndex >= (int)m_Subtitle.num_rects) return NULL; if(m_Subtitle.rects[m_SubtitleIndex] == NULL) return NULL; AVSubtitleRect& rect = *m_Subtitle.rects[m_SubtitleIndex]; CDVDOverlayImage* overlay = new CDVDOverlayImage(); overlay->iPTSStartTime = m_StartTime; overlay->iPTSStopTime = m_StopTime; overlay->replace = true; overlay->linesize = rect.w; overlay->data = (BYTE*)malloc(rect.w * rect.h); overlay->palette = (uint32_t*)malloc(rect.nb_colors*4); overlay->palette_colors = rect.nb_colors; overlay->x = rect.x; overlay->y = rect.y; overlay->width = rect.w; overlay->height = rect.h; #if (defined(LIBAVCODEC_FROM_FFMPEG) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54,71,100)) || \ (defined(LIBAVCODEC_FROM_LIBAV) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54,33,0)) // ffmpeg commit: 1885ffb03d0af28e6bac2bcc8725fa15b93f6ac9 (Nov 3 2012) // release: 1.1 (Jan 7 2013) // libav commit: 85f67c4865d8014ded2aaa64b3cba6e2970342d7 (Oct 20 2012) // release: v9 (Jan 5 2013) overlay->bForced = rect.flags != 0; #endif int right = overlay->x + overlay->width; int bottom = overlay->y + overlay->height; if(m_height == 0 && m_pCodecContext->height) m_height = m_pCodecContext->height; if(m_width == 0 && m_pCodecContext->width) m_width = m_pCodecContext->width; if(bottom > m_height) { if (bottom <= 480) m_height = 480; else if(bottom <= 576) m_height = 576; else if(bottom <= 720) m_height = 720; else if(bottom <= 1080) m_height = 1080; else m_height = bottom; } if(right > m_width) { if (right <= 720) m_width = 720; else if(right <= 1024) m_width = 1024; else if(right <= 1280) m_width = 1280; else if(right <= 1920) m_width = 1920; else m_width = right; } overlay->source_width = m_width; overlay->source_height = m_height; BYTE* s = rect.pict.data[0]; BYTE* t = overlay->data; for(int i=0;i<rect.h;i++) { memcpy(t, s, rect.w); s += rect.pict.linesize[0]; t += overlay->linesize; } for(int i=0;i<rect.nb_colors;i++) overlay->palette[i] = Endian_SwapLE32(((uint32_t *)rect.pict.data[1])[i]); m_dllAvUtil.av_free(rect.pict.data[0]); m_dllAvUtil.av_free(rect.pict.data[1]); m_dllAvUtil.av_freep(&m_Subtitle.rects[m_SubtitleIndex]); m_SubtitleIndex++; return overlay; } return NULL; }
CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() { if(m_SubtitleIndex<0) return NULL; if(m_Subtitle.num_rects == 0 && m_SubtitleIndex == 0) { // we must add an empty overlay to replace the previous one CDVDOverlay* o = new CDVDOverlay(DVDOVERLAY_TYPE_NONE); o->iPTSStartTime = m_StartTime; o->iPTSStopTime = 0; o->replace = true; m_SubtitleIndex++; return o; } if(m_Subtitle.format == 0) { if(m_SubtitleIndex >= (int)m_Subtitle.num_rects) return NULL; if(m_Subtitle.rects[m_SubtitleIndex] == NULL) return NULL; AVSubtitleRect rect = *m_Subtitle.rects[m_SubtitleIndex]; if (rect.data[0] == NULL) return NULL; m_height = m_pCodecContext->height; m_width = m_pCodecContext->width; if (m_pCodecContext->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { // ETSI EN 300 743 V1.3.1 // 5.3.1 // Absence of a DDS in a stream implies that the stream is coded in accordance with EN 300 743 (V1.2.1) [5] and that a // display width of 720 pixels and a display height of 576 lines may be assumed. if (!m_height && !m_width) { m_width = 720; m_height = 576; } } RENDER_STEREO_MODE render_stereo_mode = g_graphicsContext.GetStereoMode(); if (render_stereo_mode != RENDER_STEREO_MODE_OFF) { if (rect.h > m_height / 2) { m_height /= 2; rect.h /= 2; } else if (rect.w > m_width / 2) { m_width /= 2; rect.w /= 2; } } CDVDOverlayImage* overlay = new CDVDOverlayImage(); overlay->iPTSStartTime = m_StartTime; overlay->iPTSStopTime = m_StopTime; overlay->replace = true; overlay->linesize = rect.w; overlay->data = (uint8_t*)malloc(rect.w * rect.h); overlay->palette = (uint32_t*)malloc(rect.nb_colors*4); overlay->palette_colors = rect.nb_colors; overlay->x = rect.x; overlay->y = rect.y; overlay->width = rect.w; overlay->height = rect.h; overlay->bForced = rect.flags != 0; overlay->source_width = m_width; overlay->source_height = m_height; uint8_t* s = rect.data[0]; uint8_t* t = overlay->data; for(int i=0;i<rect.h;i++) { memcpy(t, s, rect.w); s += rect.linesize[0]; t += overlay->linesize; } for(int i=0;i<rect.nb_colors;i++) overlay->palette[i] = Endian_SwapLE32(((uint32_t *)rect.data[1])[i]); m_SubtitleIndex++; return overlay; } return NULL; }
CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() { if(m_SubtitleIndex<0) return NULL; if(m_Subtitle.num_rects == 0 && m_SubtitleIndex == 0) { // we must add an empty overlay to replace the previous one CDVDOverlay* o = new CDVDOverlay(DVDOVERLAY_TYPE_NONE); o->iPTSStartTime = 0; o->iPTSStopTime = 0; o->replace = true; m_SubtitleIndex++; return o; } if(m_Subtitle.format == 0) { if(m_SubtitleIndex >= (int)m_Subtitle.num_rects) return NULL; #if LIBAVCODEC_VERSION_INT >= (52<<10) if(m_Subtitle.rects[m_SubtitleIndex] == NULL) return NULL; AVSubtitleRect& rect = *m_Subtitle.rects[m_SubtitleIndex]; #else AVSubtitleRect& rect = m_Subtitle.rects[m_SubtitleIndex]; #endif CDVDOverlayImage* overlay = new CDVDOverlayImage(); overlay->iPTSStartTime = DVD_MSEC_TO_TIME(m_Subtitle.start_display_time); overlay->iPTSStopTime = DVD_MSEC_TO_TIME(m_Subtitle.end_display_time); overlay->replace = true; overlay->linesize = rect.w; overlay->data = (BYTE*)malloc(rect.w * rect.h); overlay->palette = (uint32_t*)malloc(rect.nb_colors*4); overlay->palette_colors = rect.nb_colors; overlay->x = rect.x; overlay->y = rect.y; overlay->width = rect.w; overlay->height = rect.h; int right = overlay->x + overlay->width; int bottom = overlay->y + overlay->height; if(m_height == 0 && m_pCodecContext->height) m_height = m_pCodecContext->height; if(m_width == 0 && m_pCodecContext->width) m_width = m_pCodecContext->width; if(bottom > m_height) { if (bottom <= 480) m_height = 480; else if(bottom <= 576) m_height = 576; else if(bottom <= 720) m_height = 720; else if(bottom <= 1080) m_height = 1080; else m_height = bottom; } if(right > m_width) { if (right <= 720) m_width = 720; else if(right <= 1024) m_width = 1024; else if(right <= 1280) m_width = 1280; else if(right <= 1920) m_width = 1920; else m_width = right; } overlay->source_width = m_width; overlay->source_height = m_height; #if LIBAVCODEC_VERSION_INT >= (52<<10) BYTE* s = rect.pict.data[0]; BYTE* t = overlay->data; for(int i=0;i<rect.h;i++) { memcpy(t, s, rect.w); s += rect.pict.linesize[0]; t += overlay->linesize; } for(int i=0;i<rect.nb_colors;i++) overlay->palette[i] = Endian_SwapLE32(((uint32_t *)rect.pict.data[1])[i]); m_dllAvUtil.av_free(rect.pict.data[0]); m_dllAvUtil.av_free(rect.pict.data[1]); m_dllAvUtil.av_freep(&m_Subtitle.rects[m_SubtitleIndex]); #else BYTE* s = rect.bitmap; BYTE* t = overlay->data; for(int i=0;i<rect.h;i++) { memcpy(t, s, rect.w); s += rect.linesize; t += overlay->linesize; } memcpy(overlay->palette, rect.rgba_palette, rect.nb_colors*4); m_dllAvUtil.av_freep(&rect.bitmap); m_dllAvUtil.av_freep(&rect.rgba_palette); #endif m_SubtitleIndex++; return overlay; } return NULL; }
bool WAVCodec::Init(const CStdString &strFile, unsigned int filecache) { m_file.Close(); if (!m_file.Open(strFile, READ_CACHED)) return false; int64_t length; WAVE_RIFFHEADER riff; bool hasFmt = false; bool hasData = false; length = m_file.GetLength(); m_file.Seek(0, SEEK_SET); m_file.Read(&riff, sizeof(WAVE_RIFFHEADER)); riff.filesize = Endian_SwapLE32(riff.filesize); if ((strncmp(riff.riff, "RIFF", 4) != 0) && (strncmp(riff.rifftype, "WAVE", 4) != 0)) return false; // read in each chunk while(length - m_file.GetPosition() >= (int64_t)sizeof(WAVE_CHUNK)) { WAVE_CHUNK chunk; m_file.Read(&chunk, sizeof(WAVE_CHUNK)); chunk.chunksize = Endian_SwapLE32(chunk.chunksize); // if it is the "fmt " chunk if (!hasFmt && (strncmp(chunk.chunk_id, "fmt ", 4) == 0)) { int64_t read; WAVEFORMATEXTENSIBLE wfx; read = std::min((DWORD)sizeof(WAVEFORMATEXTENSIBLE), chunk.chunksize); m_file.Read(&wfx, read); // get the format information m_SampleRate = Endian_SwapLE32(wfx.Format.nSamplesPerSec); m_Channels = Endian_SwapLE16(wfx.Format.nChannels ); m_BitsPerSample = Endian_SwapLE16(wfx.Format.wBitsPerSample); CLog::Log(LOGINFO, "WAVCodec::Init - Sample Rate: %d, Bits Per Sample: %d, Channels: %d", m_SampleRate, m_BitsPerSample, m_Channels); if ((m_SampleRate == 0) || (m_Channels == 0) || (m_BitsPerSample == 0)) { CLog::Log(LOGERROR, "WAVCodec::Init - Invalid data in WAVE header"); return false; } wfx.Format.wFormatTag = Endian_SwapLE16(wfx.Format.wFormatTag); wfx.Format.cbSize = Endian_SwapLE16(wfx.Format.cbSize ); // detect the file type switch(wfx.Format.wFormatTag) { case WAVE_FORMAT_PCM: CLog::Log(LOGINFO, "WAVCodec::Init - WAVE_FORMAT_PCM detected"); m_ChannelMask = 0; m_bHasFloat = false; break; case WAVE_FORMAT_IEEE_FLOAT: CLog::Log(LOGINFO, "WAVCodec::Init - WAVE_FORMAT_IEEE_FLOAT detected"); if (wfx.Format.wBitsPerSample != 32) { CLog::Log(LOGERROR, "WAVCodec::Init - Only 32bit Float is supported"); return false; } m_ChannelMask = 0; m_bHasFloat = true; break; case WAVE_FORMAT_EXTENSIBLE: if (wfx.Format.cbSize < 22) { CLog::Log(LOGERROR, "WAVCodec::Init - Corrupted WAVE_FORMAT_EXTENSIBLE header"); return false; } m_ChannelMask = Endian_SwapLE32(wfx.dwChannelMask); CLog::Log(LOGINFO, "WAVCodec::Init - WAVE_FORMAT_EXTENSIBLE detected, channel mask: %d", m_ChannelMask); wfx.SubFormat.Data1 = Endian_SwapLE32(wfx.SubFormat.Data1); wfx.SubFormat.Data2 = Endian_SwapLE16(wfx.SubFormat.Data2); wfx.SubFormat.Data3 = Endian_SwapLE16(wfx.SubFormat.Data3); if (memcmp(&wfx.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)) == 0) { CLog::Log(LOGINFO, "WAVCodec::Init - SubFormat KSDATAFORMAT_SUBTYPE_PCM Detected"); m_bHasFloat = false; } else if (memcmp(&wfx.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID)) == 0) { CLog::Log(LOGINFO, "WAVCodec::Init - SubFormat KSDATAFORMAT_SUBTYPE_IEEE_FLOAT Detected"); if (wfx.Format.wBitsPerSample != 32) { CLog::Log(LOGERROR, "WAVCodec::Init - Only 32bit Float is supported"); return false; } m_bHasFloat = true; } else { CLog::Log(LOGERROR, "WAVCodec::Init - Unsupported extensible Wave format"); return false; } break; default: CLog::Log(LOGERROR, "WAVCodec::Init - Unsupported Wave Format %d", wfx.Format.wFormatTag); return false; break; } // seek past any extra data that may be in the header m_file.Seek(chunk.chunksize - read, SEEK_CUR); hasFmt = true; } else if (!hasData && (strncmp(chunk.chunk_id, "data", 4) == 0)) { m_iDataStart = (long)m_file.GetPosition(); m_iDataLen = chunk.chunksize; chunk.chunksize += (chunk.chunksize % 2); // sanity check on the data length if (m_iDataLen > length - m_iDataStart) { CLog::Log(LOGWARNING, "WAVCodec::Init - Wave has corrupt data length of %i when it can't be longer then %"PRId64"", m_iDataLen, length - m_iDataStart); m_iDataLen = (long)(length - m_iDataStart); } // if this data chunk is empty, we will look for another data chunk that is not empty if (m_iDataLen == 0) CLog::Log(LOGWARNING, "WAVCodec::Init - Empty data chunk, will look for another"); else hasData = true; //seek past the data m_file.Seek(chunk.chunksize, SEEK_CUR); } else { // any unknown chunks just seek past m_file.Seek(chunk.chunksize, SEEK_CUR); } // dont keep reading if we have the chunks we need if (hasFmt && hasData) break; } if (!hasFmt || !hasData) { CLog::Log(LOGERROR, "WAVCodec::Init - Corrupt file, unable to locate both fmt and data chunks"); return false; } m_TotalTime = (int)(((float)m_iDataLen / (m_SampleRate * m_Channels * (m_BitsPerSample / 8))) * 1000); m_Bitrate = (int)(((float)m_iDataLen * 8) / ((float)m_TotalTime / 1000)); // ensure the parameters are valid if ((m_TotalTime <= 0) || (m_Bitrate <= 0)) { CLog::Log(LOGERROR, "WAVCodec::Init - The total time/bitrate is invalid, possibly corrupt file"); return false; } // Seek to the start of the data chunk m_file.Seek(m_iDataStart, SEEK_SET); return true; }