static int tsmf_ffmpeg_init_stream(ITSMFDecoder * decoder, const TS_AM_MEDIA_TYPE * media_type) { TSMFFFmpegDecoder * mdecoder = (TSMFFFmpegDecoder *) decoder; uint32 size; const uint8 * s; uint8 * p; mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); if (!mdecoder->codec) { LLOGLN(0, ("tsmf_ffmpeg_init_stream: avcodec_find_decoder failed.")); return 1; } mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_type = mdecoder->media_type; if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO) { if (tsmf_ffmpeg_init_video_stream(decoder, media_type)) return 1; } else if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO) { if (tsmf_ffmpeg_init_audio_stream(decoder, media_type)) return 1; } if (media_type->ExtraData) { if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. See http://haali.su/mkv/codecs.pdf */ mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size); p = mdecoder->codec_context->extradata; *p++ = 1; /* Reserved? */ *p++ = media_type->ExtraData[8]; /* Profile */ *p++ = 0; /* Profile */ *p++ = media_type->ExtraData[12]; /* Level */ *p++ = 0xff; /* Flag? */ *p++ = 0xe0 | 0x01; /* Reserved | #sps */ s = media_type->ExtraData + 20; size = ((uint32)(*s)) * 256 + ((uint32)(*(s + 1))); memcpy(p, s, size + 2); s += size + 2; p += size + 2; *p++ = 1; /* #pps */ size = ((uint32)(*s)) * 256 + ((uint32)(*(s + 1))); memcpy(p, s, size + 2); } else { /* Add a padding to avoid invalid memory read in some codec */ mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size); memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize); memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); } } if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; return 0; }
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) { BYTE *p; UINT32 size; const BYTE *s; TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); if (!mdecoder->codec) { WLog_ERR(TAG, "avcodec_find_decoder failed."); return FALSE; } mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_type = mdecoder->media_type; switch(mdecoder->media_type) { case AVMEDIA_TYPE_VIDEO: if (!tsmf_ffmpeg_init_video_stream(decoder, media_type)) return FALSE; break; case AVMEDIA_TYPE_AUDIO: if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) return FALSE; break; default: WLog_ERR(TAG, "unknown media_type %d", mdecoder->media_type); break; } if (media_type->ExtraData) { /* Add a padding to avoid invalid memory read in some codec */ mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; mdecoder->codec_context->extradata = calloc(1, mdecoder->codec_context->extradata_size); if (!mdecoder->codec_context->extradata) return FALSE; if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. See http://haali.su/mkv/codecs.pdf */ p = mdecoder->codec_context->extradata; *p++ = 1; /* Reserved? */ *p++ = media_type->ExtraData[8]; /* Profile */ *p++ = 0; /* Profile */ *p++ = media_type->ExtraData[12]; /* Level */ *p++ = 0xff; /* Flag? */ *p++ = 0xe0 | 0x01; /* Reserved | #sps */ s = media_type->ExtraData + 20; size = ((UINT32)(*s)) * 256 + ((UINT32)(*(s + 1))); memcpy(p, s, size + 2); s += size + 2; p += size + 2; *p++ = 1; /* #pps */ size = ((UINT32)(*s)) * 256 + ((UINT32)(*(s + 1))); memcpy(p, s, size + 2); } else { memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize); memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); } } if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; return TRUE; }