然后,进入video\MPEG4-ffmpeg目录下看mpeg4.cxx,这里包含了完整的RFC解包重组及MPEG4解码的源码。直接编译可能通不过,好在代码写的非常整齐,提取出来就是了。解包解码只要看这一个函数:
- bool MPEG4DecoderContext::DecodeFrames(const BYTE * src, unsigned & srcLen,
- BYTE * dst, unsigned & dstLen,
- unsigned int & flags)
- {
- if (!FFMPEGLibraryInstance.IsLoaded())
- return 0;
-
-
- RTPFrame srcRTP(src, srcLen);
- RTPFrame dstRTP(dst, dstLen, RTP_DYNAMIC_PAYLOAD);
- dstLen = 0;
- flags = 0;
-
- int srcPayloadSize = srcRTP.GetPayloadSize();
- SetDynamicDecodingParams(true);
-
-
- if(_lastPktOffset + srcPayloadSize < _encFrameLen)
- {
-
- memcpy(_encFrameBuffer + _lastPktOffset, srcRTP.GetPayloadPtr(),
- srcPayloadSize);
- _lastPktOffset += srcPayloadSize;
- }
- else {
-
-
-
-
-
-
-
-
-
-
-
- TRACE(1, "MPEG4\tDecoder\tWaiting for an I-Frame");
- _lastPktOffset = 0;
- flags = (_gotAGoodFrame ? PluginCodec_ReturnCoderRequestIFrame : 0);
- _gotAGoodFrame = false;
- return 1;
- }
-
-
- int got_picture = 0;
- if (srcRTP.GetMarker()) {
- _frameNum++;
- int len = FFMPEGLibraryInstance.AvcodecDecodeVideo
- (_avcontext, _avpicture, &got_picture,
- _encFrameBuffer, _lastPktOffset);
-
- if (len >= 0 && got_picture) {
- #ifdef LIBAVCODEC_HAVE_SOURCE_DIR
- if (DecoderError(_keyRefreshThresh)) {
-
- flags = (_gotAGoodFrame ? PluginCodec_ReturnCoderRequestIFrame : 0);
- _gotAGoodFrame = false;
- }
- #endif
- TRACE_UP(4, "MPEG4\tDecoder\tDecoded " << len << " bytes" <<
- ", Resolution: " << _avcontext->width << "x" << _avcontext->height);
-
- if (!_disableResize
- && (_frameWidth != (unsigned)_avcontext->width
- || _frameHeight != (unsigned)_avcontext->height))
- {
-
- _frameWidth = _avcontext->width;
- _frameHeight = _avcontext->height;
-
- SetDynamicDecodingParams(true);
- return true;
- }
-
-
- int frameBytes = (_frameWidth * _frameHeight * 3) / 2;
- PluginCodec_Video_FrameHeader * header
- = (PluginCodec_Video_FrameHeader *)dstRTP.GetPayloadPtr();
- header->x = header->y = 0;
- header->width = _frameWidth;
- header->height = _frameHeight;
- unsigned char *dstData = OPAL_VIDEO_FRAME_DATA_PTR(header);
- for (int i=0; i<3; i ++) {
- unsigned char *srcData = _avpicture->data[i];
- int dst_stride = i ? _frameWidth >> 1 : _frameWidth;
- int src_stride = _avpicture->linesize[i];
- int h = i ? _frameHeight >> 1 : _frameHeight;
- if (src_stride==dst_stride) {
- memcpy(dstData, srcData, dst_stride*h);
- dstData += dst_stride*h;
- }
- else
- {
- while (h--) {
- memcpy(dstData, srcData, dst_stride);
- dstData += dst_stride;
- srcData += src_stride;
- }
- }
- }
-
- dstRTP.SetPayloadSize(sizeof(PluginCodec_Video_FrameHeader)
- + frameBytes);
- dstRTP.SetPayloadType(RTP_DYNAMIC_PAYLOAD);
- dstRTP.SetTimestamp(srcRTP.GetTimestamp());
- dstRTP.SetMarker(true);
- dstLen = dstRTP.GetFrameLen();
- flags = PluginCodec_ReturnCoderLastFrame;
- _gotAGoodFrame = true;
- }
- else {
- TRACE(1, "MPEG4\tDecoder\tDecoded "<< len <<
- " bytes without getting a Picture...");
-
- flags = (_gotAGoodFrame ? PluginCodec_ReturnCoderRequestIFrame : 0);
- _gotAGoodFrame = false;
- }
- _lastPktOffset = 0;
- }
- return true;
- }
写的非常非常的明白:if (srcRTP.GetMarker()),到了这里表示收满了一包,开始去解码。
mpeg4-es的RFC还原重组就这么简单,下一步的解码,就涉及到用libavcodec.dll了。
(sxcong) |