1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | HBITMAP loadPictureFromFile(LPCTSTR szFile) { HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hFile) return NULL; DWORD dwFileSize = GetFileSize(hFile, NULL); LPVOID pvData = NULL; HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); pvData = GlobalLock(hGlobal); DWORD dwBytesRead = 0; BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL); GlobalUnlock(hGlobal); CloseHandle(hFile); LPSTREAM pStm = NULL; HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); LPPICTURE gpPicture; hr = ::OleLoadPicture(pStm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture); pStm->Release(); OLE_HANDLE picHandle; gpPicture->get_Handle(&picHandle); HDC hdc = ::CreateCompatibleDC(NULL); ::SelectObject(hdc, (HGDIOBJ)picHandle); HBITMAP hRet = (HBITMAP)::GetCurrentObject(hdc, OBJ_BITMAP); DeleteDC(hdc); // gpPicture->Release(); // 这里不能释放gpPicture,否则返回的hRet是野指针数据 return hRet; } |
euhat
Bash读取某一行某一列
打印第11行:
sed -n "11, 1p" /tmp/tmp.txt
或者
awk 'NR == 11 {print}' /tmp/tmp.txt
打印第3列:
awk '{print $3;}' /tmp/tmp.txt
打印总行数:
awk 'END {print NR}' /tmp/tmp.txt
EuhatRtsp开源
这是我写的一款开源软件,主要用于安卓设备上的RTSP流获取及显示。更多信息,请参看:
MFC CScrollBar拖动完后总跑到零位置
原因是
- 要处理SB_ENDSCROLL事件。
- 一定要在适当的地方GetScrollPos或SetScrollPos。
正确示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | void SampleDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { int iMin = 0, iMax = 0; pScrollBar->GetScrollRange(&iMin, &iMax); // nPos = pScrollBar->GetScrollPos(); // 此处这句话一定不能有 switch (nSBCode) { case SB_THUMBTRACK: break; case SB_LINELEFT: nPos = pScrollBar->GetScrollPos(); // 此处这句话一定要有 nPos--; if (nPos < (UINT)iMin) nPos = 0; break; case SB_LINERIGHT: nPos = pScrollBar->GetScrollPos(); // 此处这句话一定要有 nPos++; if (nPos >= (UINT)iMax) nPos = iMax - 1; break; case SB_ENDSCROLL: nPos = pScrollBar->GetScrollPos(); // 此处这句话一定要有 break; default: break; } pScrollBar->SetScrollPos(nPos, 1); // 此处这句话也一定要有 // Todo real work with nPos. CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar); } |
error C4839: 作为可变参数函数的参数的非标准用法
报错语句为:
1 | _stprintf_s(filepath, _T("%s\\%s"), curpath, CA2T(iniFilePath)); |
改为如下就不报错了:
1 2 | CString iniFilePathT = CA2T(iniFilePath); _stprintf_s(filepath, _T("%s\\%s"), curpath, (LPCTSTR)iniFilePathT); |
targetSdkVersion未安装应用程式
发布后在Android 6.1的手机上安装不了,显示“未安装应用程序”,检查源码发现build.gradle文件中
1 2 3 4 | defaultConfig { minSdkVersion 14 targetSdkVersion 27 } |
于是,把targetSdkVersion改为23,而发布release版时,Signature Versions只选V1(Jar Signature)。
再将生成的apk包在安卓6.1手机上装,顺利安装成功。
HLSL显示贴图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | float4x4 worldViewProj : WorldViewProjection; struct VS_INPUT { float3 pos : POSITION; float2 tex : TEXCOORD0; }; struct VS_OUTPUT { float4 pos : POSITION; float2 tex : TEXCOORD0; }; VS_OUTPUT mainVS(VS_INPUT input) { VS_OUTPUT vsOut; vsOut.pos = mul(float4(input.pos, 1), worldViewProj); vsOut.tex = input.tex; // vsOut.tex.xy = vsOut.pos.zw; return vsOut; } texture tex0; sampler2D sample0 = sampler_state { Texture = <tex0>; /* MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; AddressU = CLAMP; AddressV = CLAMP; */ }; float4 mainPS(float2 tex : TEXCOORD0) : COLOR { return tex2D(sample0, tex); // return tex.x / tex.y; } technique technique0 { pass p0 { VertexShader = compile vs_3_0 mainVS(); PixelShader = compile ps_3_0 mainPS(); } } |
yv12 to nv21
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | void nv212Yv12(char *nv21, char *yv12, int width, int height) { int frameSize = width * height; memcpy(yv12, nv21, frameSize); nv21 += frameSize; yv12 += frameSize; int halfWidth = width / 2; int halfHeight = height / 2; int quadFrame = halfWidth * halfHeight; for (int i = 0; i < halfHeight; i++) { for (int j = 0; j < halfWidth; j++) { *(yv12 + i * halfWidth + j) = *nv21++; *(yv12 + quadFrame + i * halfWidth + j) = *nv21++; } } } void yv122Nv21(char *yv12, char *nv21, int width, int height) { int frameSize = width * height; memcpy(nv21, yv12, frameSize); nv21 += frameSize; yv12 += frameSize; int halfWidth = width / 2; int halfHeight = height / 2; int quadFrame = halfWidth * halfHeight; for (int i = 0; i < halfHeight; i++) { for (int j = 0; j < halfWidth; j++) { *nv21++ = *(yv12 + i * halfWidth + j); *nv21++ = *(yv12 + quadFrame + i * halfWidth + j); } } } |
NDK硬解h264
有几点须注意,
- 不要让硬解码器自已绘制表面,也就是AMediaCodec_configure传入的surface应设为空。否则运行时间长了,会出现“weak global reference table overflow”的崩机错误。
- 我之前文章里也说过了,不要静态链编libmediandk.so,老的安卓机上没有这个库,要动态检测加载,详细过程见之后代码。
- AMediaCodec_dequeueInputBuffer不是每一次都返回成功,如果失败了而丢弃h264数据帧,则最终的播放效果就时不时出现花屏,正确处理见之后代码。
- 硬解码器解出的数据默认可能是NV12格式也可能是YV12格式,不同的手机不一样,预先配置解码器的"color-format"为19,也没用。为了与ffmpeg解出的数据一致为YU12格式,统一地我们自已转。
以下是源码,摘选自EuhatRtsp开源软件,经历过长时间拷机运行没问题。其网址是:http://euhat.com/rtsp.html
DecoderHard.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #pragma once #include "DecodeOp.h" class AMediaCodec; class EuhatDecoderHard : public EuhatDecoderBase { int updateSpsAndPps(); int spsChanged_; int ppsChanged_; char *sps_; char *pps_; int width_; int height_; int oriHeight_; int colorFormat_; int stride_; int sliceHeight_; int cropTop_; int cropBottom_; int cropLeft_; int cropRight_; int isCodecInited_; void *surface_; int surfaceChanged_; public: EuhatDecoderHard(); virtual ~EuhatDecoderHard(); virtual int init(EuhatDecoderCallback callback, void *context); virtual int fini(); virtual int updateSps(const char *sps); virtual int updatePps(const char *pps); virtual int updateWH(int width, int height); virtual int updateSurface(void *surface); virtual int decode(char *frame, int frameLen); static int canWork(); AMediaCodec *mediaCodec_; }; |
数据结构好文推荐
红黑树演示 https://sandbox.runjs.cn/show/2nngvn8w 有哪些最新的机器学习可视化工具? https://www.toutiao.com/a6567983574299967757/ NDK-FFmpeg视频解码 http://www.imooc.com/article/80058 RSA加密原理 http://blog.jobbole.com/42699/ |