FFmpegH264Decoder<LIBAV_VER>::DecodeResult FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample, uint8_t* aData, int aSize) { AVPacket packet; av_init_packet(&packet); packet.data = aData; packet.size = aSize; packet.dts = aSample->mTimecode; packet.pts = aSample->mTime; packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0; packet.pos = aSample->mOffset; if (!PrepareFrame()) { NS_WARNING("FFmpeg h264 decoder failed to allocate frame."); mCallback->Error(); return DecodeResult::DECODE_ERROR; } // Required with old version of FFmpeg/LibAV mFrame->reordered_opaque = AV_NOPTS_VALUE; int decoded; int bytesConsumed = avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet); FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d " "(Input: pts(%lld) dts(%lld) Output: pts(%lld) " "opaque(%lld) pkt_pts(%lld) pkt_dts(%lld))", bytesConsumed, decoded, packet.pts, packet.dts, mFrame->pts, mFrame->reordered_opaque, mFrame->pkt_pts, mFrame->pkt_dts); if (bytesConsumed < 0) { NS_WARNING("FFmpeg video decoder error."); mCallback->Error(); return DecodeResult::DECODE_ERROR; } // If we've decoded a frame then we need to output it if (decoded) { int64_t pts = GetPts(packet); FFMPEG_LOG("Got one frame output with pts=%lld opaque=%lld", pts, mCodecContext->reordered_opaque); VideoInfo info; info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight); VideoData::YCbCrBuffer b; b.mPlanes[0].mData = mFrame->data[0]; b.mPlanes[0].mStride = mFrame->linesize[0]; b.mPlanes[0].mHeight = mFrame->height; b.mPlanes[0].mWidth = mFrame->width; b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0; b.mPlanes[1].mData = mFrame->data[1]; b.mPlanes[1].mStride = mFrame->linesize[1]; b.mPlanes[1].mHeight = (mFrame->height + 1) >> 1; b.mPlanes[1].mWidth = (mFrame->width + 1) >> 1; b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0; b.mPlanes[2].mData = mFrame->data[2]; b.mPlanes[2].mStride = mFrame->linesize[2]; b.mPlanes[2].mHeight = (mFrame->height + 1) >> 1; b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1; b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0; nsRefPtr<VideoData> v = VideoData::Create(info, mImageContainer, aSample->mOffset, pts, aSample->mDuration, b, aSample->mKeyframe, -1, gfx::IntRect(0, 0, mCodecContext->width, mCodecContext->height)); if (!v) { NS_WARNING("image allocation error."); mCallback->Error(); return DecodeResult::DECODE_ERROR; } mCallback->Output(v); return DecodeResult::DECODE_FRAME; } return DecodeResult::DECODE_NO_FRAME; }
bool CppArcInfo (vector < double >x, vector < double >y, vector < double >circle, vector < double >&ArcInfo) { // calculate the start and end angle of the arc formed by the input points, and also calculate the angle of arc. // circle: [yc, xc, r] // InSemiCircle: Np*1 bool vector, Np is the number of elements in x or y. It indicates whether points in the range of semicircle protruding to scan position. // ArcInfo: [StartAngle, EndAngle, ArcAngle], all the angles in unit of radian. // if ArcAngle is zero, it indicates that no valid arc is detected from the points, with the information about its corresponding circle center and scan position. if (circle.size () != 3) { #ifdef MATLABPRINT mexPrintf ("CppArcInfo ==> circle must be vector with 3 elements!\n"); #endif ArcInfo.clear (); return false; } if (x.size () != y.size () || x.size () < 2) { #ifdef MATLABPRINT mexPrintf ("CppArcInfo ==> x and y must be vectors with the same number of element, at least 2 elements!\n"); #endif ArcInfo.clear (); return false; } vector < double >angle (x.size (), -1.0); double minangle = 2 * PI, maxangle = 0.0, maxangleInPi = 0.0, minangleOutPi = 2 * PI; double arrow[2]; unsigned int pnum = 0; // count the number of points in semicircle protruding to scan position. // calculate the angle of vector (x-xc, y-yc) counterclockwise from x axis // estimate the arc angle by rasterizing the radius angle into equal divisions and counting the points within each division. double AngleResolution = 0.01 / 180.0 * PI; // the resolution of angle is 0.01 degree. int AngleNum = 36000; //static_cast<int>(2*PI/AngleResolution)+1; int tempind; vector < bool > GetPts (AngleNum, false); vector < double >MinAngleInDiv (AngleNum, 2 * PI); vector < double >MaxAngleInDiv (AngleNum, 0); for (unsigned int i = 0; i < x.size (); i++) { arrow[0] = x[i] - circle[1]; arrow[1] = y[i] - circle[0]; if (arrow[0] == 0) { if (arrow[1] == 0) { #ifdef MATLABPRINT mexPrintf ("CppArcInfo ==> circle center is at the same position with one point, wrong circle center!!\n"); #endif ArcInfo.clear (); return false; } } angle[i] = atan2 (arrow[1], arrow[0]); if (angle[i] < 0) { angle[i] += 2 * PI; } tempind = static_cast < int >(angle[i] / AngleResolution); GetPts[tempind] = true; if (angle[i] < MinAngleInDiv[tempind]) { MinAngleInDiv[tempind] = angle[i]; } if (angle[i] > MaxAngleInDiv[tempind]) { MaxAngleInDiv[tempind] = angle[i]; } } ArcInfo.clear (); ArcInfo.resize (3, 0.0); vector < int >StartAngleDiv, EndAngleDiv, BlankDivs; StartAngleDiv.clear (); EndAngleDiv.clear (); BlankDivs.clear (); bool blankflag = false; int blankdivnum = 0, blankblocknum = 0; int scancount = 0; // start from zero angle (counter-clockwise from x positive), search the consecutive blank angle divisions. for (int i = 0; i < 2 * AngleNum - 1 && scancount < AngleNum; i++) { if (!blankflag && GetPts[i % AngleNum] && !GetPts[(i + 1) % AngleNum]) { StartAngleDiv.push_back (i % AngleNum); blankflag = true; blankblocknum++; BlankDivs.push_back (0); scancount++; continue; } if (blankflag && !GetPts[i % AngleNum]) { BlankDivs[blankblocknum - 1]++; scancount++; if (GetPts[(i + 1) % AngleNum]) { EndAngleDiv.push_back ((i + 1) % AngleNum); blankflag = false; } continue; } if (GetPts[i % AngleNum]) { scancount++; } } if (BlankDivs.size () == 0) { if (!scancount) { ArcInfo[0] = 0; ArcInfo[1] = 0; ArcInfo[2] = mxGetInf (); } else { ArcInfo[0] = 0; ArcInfo[1] = 2 * PI; ArcInfo[2] = 2 * PI; } return true; } vector < int >::iterator MaxBlankDiv; MaxBlankDiv = max_element (BlankDivs.begin (), BlankDivs.end ()); int MaxInd = static_cast < int >(MaxBlankDiv - BlankDivs.begin ()); int MaxBlankDivCount = count (BlankDivs.begin (), BlankDivs.end (), *MaxBlankDiv); if (*MaxBlankDiv < 2) { ArcInfo[0] = 0; ArcInfo[1] = 2 * PI; ArcInfo[2] = 2 * PI; } else { if (MaxBlankDivCount > 1) { // This situation needs further processing to obtain more accurate arc angle. ArcInfo[0] = 0; ArcInfo[1] = 0; ArcInfo[2] = mxGetInf (); } else { ArcInfo[0] = MaxAngleInDiv[StartAngleDiv[MaxInd]]; ArcInfo[1] = MinAngleInDiv[EndAngleDiv[MaxInd]]; ArcInfo[2] = BlankDivs[MaxInd] * AngleResolution; ArcInfo[2] += AngleResolution * (StartAngleDiv[MaxInd] + 1) - ArcInfo[0]; ArcInfo[2] += ArcInfo[1] - AngleResolution * EndAngleDiv[MaxInd]; ArcInfo[2] = 2 * PI - ArcInfo[2]; } } return true; }