sdl

#include "myf4.h"



////////////////////////////////









#include "iostream"
#include "stdlib.h"
#include <string.h>
#include <math.h>
#include <chrono> //C++11時間類標準模板庫

#ifndef _DEBUG
#define  _HZG_SDL_ 1
#endif

#ifdef _WIN32
//Windows
extern "C"
{
#if _MSC_VER
#define snprintf _snprintf
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavfilter/avfilter.h"
#include "libavutil/imgutils.h"
#include "libavutil/fifo.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libswresample/swresample.h"

#ifdef _HZG_SDL_
#include "SDL.h"
	//#include "SDL2\SDL.h"
#endif

};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libswresample/swresample.h>
#include <SDL2/SDL.h>
#ifdef __cplusplus
};
#endif
#endif


using namespace std;

#define  _CRT_SECURE_NO_WARNINGS






/////////////////////////////////////


#include <fstream>
#include <iostream>

using namespace std;
int saveImgFile(char* _buf, int _len, std::string _fileName)
{
	ofstream file;
	try {
		file.open(_fileName, ios::out | ios::binary);
	}
	catch (...) {
		cout << "open file failed." << endl;
		return -1;
	}

	if (!file.is_open()) {
		cout << "open file failed2." << endl;
		return -1;
	}

	file.write(_buf, _len);

	file.close();

	return 0;
}
int RotationRight90(unsigned char * src, int srcW, int srcH, int channel)
{
	unsigned char * tempSrc = NULL;
	int mSize = srcW * srcH * sizeof(char) * channel;
	int i = 0;
	int j = 0;
	int k = 0;
	int desW = 0;
	int desH = 0;

	desW = srcH;
	desH = srcW;

	tempSrc = (unsigned char *)malloc(sizeof(char) * srcW * srcH * channel);
	memcpy(tempSrc, src, mSize);

	for (i = 0; i < desH; i++)
	{
		for (j = 0; j < desW; j++)
		{
			for (k = 0; k < channel; k++)
			{
				src[(i * desW + j) * channel + k] = tempSrc[((srcH - 1 - j) * srcW + i) * channel + k];

			}

		}
	}

	free(tempSrc);
	return 0;
}

void Rotate90(const AVFrame* src, AVFrame* dst)
{
	int half_width = src->width >> 1;
	int half_height = src->height >> 1;




	int size = src->linesize[0] * src->height;
	int half_size = size >> 2;




	for (int j = 0, n = 0; j < src->width; j++) {
		int pos = size;
		for (int i = src->height - 1; i >= 0; i--) {
			pos -= src->linesize[0];
			dst->data[0][n++] = src->data[0][pos + j];
		}
	}




	for (int j = 0, n = 0; j < half_width; j++) {
		int pos = half_size;
		for (int i = half_height - 1; i >= 0; i--) {
			pos -= src->linesize[1];
			dst->data[1][n] = src->data[1][pos + j];
			dst->data[2][n++] = src->data[2][pos + j];
		}
	}




	dst->height = src->width;
	dst->width = src->height;
}

void frame_rotate_90WithSorrce(AVFrame* src,  AVFrame* des)
{
	int n = 0;
	int hw = src->width >> 1;
	int hh = src->height >> 1;
	int size = src->width * src->height;
	int hsize = size >> 2;

	int pos = 0;
	//copy y
	for (int j = 0; j < src->width; j++)
	{
		pos = size;
		for (int i = src->height - 1; i >= 0; i--)
		{
			pos -= src->width;
			des->data[0][n++] = src->data[0][pos + j];
		}
	}
	//copy uv
	n = 0;
	for (int j = 0; j < hw; j++)
	{
		pos = hsize;
		for (int i = hh - 1; i >= 0; i--)
		{
			pos -= hw;
			des->data[1][n] = src->data[1][pos + j];
			des->data[2][n] = src->data[2][pos + j];
			n++;
		}
	}

	des->linesize[0] = src->height;
	des->linesize[1] = src->height >> 1;
	des->linesize[2] = src->height >> 1;
	des->height = src->width;
	des->width = src->height;
}

// 逆時針90
void YUVRotate90(BYTE *des, BYTE *src, int width, int height)
{
	int i = 0, j = 0, n = 0;
	int hw = width / 2, hh = height / 2;
	for (j = width; j > 0; j--) {
		for (i = 0; i < height; i++)
		{
			des[n++] = src[width*i + j];
		}
	}

	unsigned char *ptmp = src + width*height;
	for (j = hw; j > 0; j--) {
		for (i = 0; i < hh; i++)
		{
			des[n++] = ptmp[hw*i + j];
		}
	}

	ptmp = src + width*height * 5 / 4;
	for (j = hw; j > 0; j--){
		for (i = 0; i < hh; i++)
		{
			des[n++] = ptmp[hw*i + j];
		}
	}
}

//逆時針180
void yuv_rotate_180(const char* yuvfilename, int width, int height){
	FILE* fp = NULL;
	fopen_s(&fp, yuvfilename, "rb");
	uint8_t* yuvbuf = new uint8_t[width*height * 3 / 2];
	fread(yuvbuf, width*height * 3 / 2, 1, fp);
	fclose(fp);
	uint8_t* dstbuf = new uint8_t[width*height * 3 / 2];
	int idx = 0;
	//旋轉180:將右下角的點作爲第一個點,從右往左,從下往上取點
	//Y 寬:[0,w-1]  高:[0,h-1]
	for (int i = height - 1; i >= 0; i--){
		for (int j = width - 1; j >= 0; j--){
			dstbuf[idx++] = *(yuvbuf + (i*width + j));
		}
	}
	uint8_t* uheader = yuvbuf + width*height;
	//U
	for (int i = height / 2 - 1; i >= 0; i--){
		for (int j = width / 2 - 1; j >= 0; j--){
			dstbuf[idx++] = *(uheader + (i*width / 2 + j));
		}
	}
	uint8_t* vheader = uheader + width*height / 4;
	//V
	for (int i = height / 2 - 1; i >= 0; i--){
		for (int j = width / 2 - 1; j >= 0; j--){
			dstbuf[idx++] = *(vheader + (i*width / 2 + j));
		}
	}
	FILE* fpout = NULL;
	fopen_s(&fpout, "yuv_rotate_180.yuv", "wb");
	fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
	fclose(fpout);
	delete[] yuvbuf;
	delete[] dstbuf;
}

//逆時針旋轉180後鏡像
void yuv_rotate_180_by_ssz(const char* yuvfilename, int width, int height){
	FILE* fp = NULL;
	fopen_s(&fp, yuvfilename, "rb");
	uint8_t* yuvbuf = new uint8_t[width*height * 3 / 2];
	fread(yuvbuf, width*height * 3 / 2, 1, fp);
	fclose(fp);

	uint8_t* dstbuf = new uint8_t[width*height * 3 / 2];
	int idx = 0;
	//旋轉180:將左下角的點作爲第一個點,從左往右,從下往上取點
	//Y 寬:[0,w-1]  高:[0,h-1]
	for (int i = height - 1; i >= 0; i--){
		for (int j = 0; j <= width - 1; j++){
			dstbuf[idx++] = *(yuvbuf + (i*width + j));
		}
	}
	uint8_t* uheader = yuvbuf + width*height;
	//U
	for (int i = height / 2 - 1; i >= 0; i--){
		for (int j = 0; j <= width / 2 - 1; j++){
			dstbuf[idx++] = *(uheader + (i*width / 2 + j));
		}
	}
	uint8_t* vheader = uheader + width*height / 4;
	//V
	for (int i = height / 2 - 1; i >= 0; i--){
		for (int j = 0; j <= width / 2 - 1; j++){
			dstbuf[idx++] = *(vheader + (i*width / 2 + j));
		}
	}
	FILE* fpout = NULL;
	fopen_s(&fpout, "yuv_rotate_180_by_ssz2.yuv", "wb");
	fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
	fclose(fpout);
	delete[] yuvbuf;
	delete[] dstbuf;
}

//逆時針旋轉90
void rotate90YUV420P(char *yuvfilename, int width, int height)
{
	int i, j, k, p, q;

	FILE* fp = NULL;
	fopen_s(&fp, yuvfilename, "rb");
	uint8_t* yuvbuf = new uint8_t[width*height * 3 / 2];
	fread(yuvbuf, width*height * 3 / 2, 1, fp);
	fclose(fp);
	uint8_t* dstbuf = new uint8_t[width*height * 3 / 2];

	char *dest = (char*)dstbuf;
	char* src = (char*)yuvbuf;

	// rotate Y
	for (j = 0; j < width; j++){
		for (i = 1; i <= height; i++){
			*dest++ = *(src + i*width - j);
		}
	}

	// rotate U
	char *src_u = src + width*height;
	for (p = 0; p < width / 2; p++){
		for (k = 1; k <= height / 2; k++){
			*dest++ = *(src_u + k*width / 2 - p);

		}
	}

	// rotate V
	char *src_v = src + width*height * 5 / 4;
	for (p = 0; p < width / 2; p++){
		for (k = 1; k <= height / 2; k++){
			*dest++ = *(src_v + k*width / 2 - p);
		}
	}

	FILE* fpout = NULL;
	fopen_s(&fpout, "rotate90YUV420P.yuv", "wb");
	fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
	fclose(fpout);
	delete[] yuvbuf;
	delete[] dstbuf;
}

//順時針旋轉90
void yuv_rotate_90_by_ssz(const char* yuvfilename, int width, int height){
	FILE* fp = NULL;
	fopen_s(&fp, yuvfilename, "rb");
	uint8_t* yuvbuf = new uint8_t[width*height * 3 / 2];
	fread(yuvbuf, width*height * 3 / 2, 1, fp);
	fclose(fp);

	uint8_t* dstbuf = new uint8_t[width*height * 3 / 2];
	int idx = 0;
	//旋轉180:將左下角的點作爲第一個點,從右往左,從下往上取點
	//Y 寬:[0,w-1]  高:[0,h-1]
	for (int i = 0; i <= width - 1; i++){
		for (int j = height - 1; j >= 0; j--){
			dstbuf[idx++] = *(yuvbuf + (j*width + i));
		}
	}
	uint8_t* uheader = yuvbuf + width*height;
	//U
	int hw = width / 2;
	int hh = height / 2;

	for (int i = 0; i <= hw - 1; i++){
		for (int j = hh - 1; j >= 0; j--){
			dstbuf[idx++] = *(uheader + (j*hw + i));
		}
	}

	uint8_t* vheader = uheader + width*height / 4;
	//V
	for (int i = 0; i <= hw - 1; i++){
		for (int j = hh - 1; j >= 0; j--){
			dstbuf[idx++] = *(vheader + (j*hw + i));
		}
	}
	FILE* fpout = NULL;
	fopen_s(&fpout, "zssz-90-4.yuv", "wb");
	fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
	fclose(fpout);
	delete[] yuvbuf;
	delete[] dstbuf;
}

//鏡像翻轉
void yuv_flip(const char* yuvfilename, int width, int height){

	FILE* fp = NULL;
	fopen_s(&fp, yuvfilename, "rb");
	uint8_t* yuvbuf = new uint8_t[width*height * 3 / 2];
	fread(yuvbuf, width*height * 3 / 2, 1, fp);
	fclose(fp);
	uint8_t* dstbuf = new uint8_t[width*height * 3 / 2];
	int idx = 0;
	//水平翻轉:將右上角的點作爲第一個點,從右往左,從上往下取點
	//Y 寬:[0,w-1]  高:[0,h-1]
	for (int i = 0; i < height; i++){
		for (int j = width - 1; j >= 0; j--){
			dstbuf[idx++] = *(yuvbuf + (i*width + j));
		}
	}
	uint8_t* uheader = yuvbuf + width*height;
	//U
	for (int i = 0; i < height / 2; i++){
		for (int j = width / 2 - 1; j >= 0; j--){
			dstbuf[idx++] = *(uheader + (i*width / 2 + j));
		}
	}
	uint8_t* vheader = uheader + width*height / 4;
	//V
	for (int i = 0; i < height / 2; i++){
		for (int j = width / 2 - 1; j >= 0; j--){
			dstbuf[idx++] = *(vheader + (i*width / 2 + j));
		}
	}
	FILE* fpout = NULL;
	fopen_s(&fpout, "flip_out.yuv", "wb");
	fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
	fclose(fpout);
	delete[] yuvbuf;
	delete[] dstbuf;
}


#define MAX_LOADSTRING 100

// 全局變量: 
HINSTANCE hInst;								// 當前實例
TCHAR szTitle[MAX_LOADSTRING];					// 標題欄文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口類名

// 此代碼模塊中包含的函數的前向聲明: 
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO:  在此放置代碼。
	MSG msg;
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_MYF4, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// 執行應用程序初始化: 
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MYF4));



	//////////////////////////////////////////////////////////////////////////


	char *fname = "./net-download-test.264";

	char errbuf[256] = { 0 };
	int iRes = 0;
	int vindex = -1;
	AVFormatContext *fctx = NULL;
	AVCodecContext *cctx = NULL;
	AVCodec *c = NULL;
	AVPacket *pkt = NULL;
	AVFrame *fr = NULL;
	AVFrame *yuv = NULL;
	uint8_t *buf = NULL;
	int vsize;
	struct SwsContext *imgCtx = NULL;

#ifdef _HZG_SDL_
	SDL_Window *sw = NULL;
	SDL_Renderer *sr = NULL;
	SDL_Texture *ste = NULL;
	SDL_Rect srect = { 0 };
	//	av_register_all();  //ffmpeg 4.0 After no
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
	{
		cout << "SDL init failed!" << endl;
		return -1;
	}
#endif

	fctx = avformat_alloc_context();
	if ((iRes = avformat_open_input(&fctx, fname, NULL, NULL)) != 0)
	{
		cout << "File open failed!" << endl;
		return -1;
	}

	if (avformat_find_stream_info(fctx, NULL) < 0)
	{
		cout << "Stream find failed!\n";
		return -1;
	}
	av_dump_format(fctx, -1, fname, NULL);

	for (int i = 0; i < fctx->nb_streams; i++)
	{
		if (fctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
			vindex = i;
	}
	if (vindex == -1)
	{
		cout << "Codec find failed!" << endl;
		return -1;
	}

	cctx = avcodec_alloc_context3(NULL);
	if (avcodec_parameters_to_context(cctx, fctx->streams[vindex]->codecpar) < 0)
	{
		cout << "Copy stream failed!" << endl;
		return -1;
	}
	c = avcodec_find_decoder(cctx->codec_id);
	if (!c) {
		cout << "Find Decoder failed!" << endl;
		return -1;
	}
	if (avcodec_open2(cctx, c, NULL) != 0) {
		cout << "Open codec failed!" << endl;
		return -1;
	}

#ifdef _HZG_SDL_
	sw = SDL_CreateWindow("video", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 680, 540, SDL_WINDOW_OPENGL);
	sr = SDL_CreateRenderer(sw, -1, 0);
	ste = SDL_CreateTexture(sr, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, cctx->width, cctx->height);
	if (!sw || !sr || !ste) {
		cout << "Create SDL windows failed!" << endl;
		return -1;
	}
	srect.w = cctx->width;
	srect.h = cctx->height;
#endif

	imgCtx = sws_getContext(cctx->width, cctx->height, cctx->pix_fmt, cctx->width, cctx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
	if (!imgCtx) {
		cout << "Get swscale context failed!" << endl;
		return -1;
	}
	pkt = av_packet_alloc();
	fr = av_frame_alloc();
	yuv = av_frame_alloc();
	vsize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, cctx->width, cctx->height, 1);
	buf = (uint8_t *)av_malloc(vsize);
	av_image_fill_arrays(yuv->data, yuv->linesize, buf, AV_PIX_FMT_YUV420P, cctx->width, cctx->height, 1);
	while (av_read_frame(fctx, pkt) >= 0) {
		if (pkt->stream_index == vindex) {
			if ((iRes = avcodec_send_packet(cctx, pkt)) != 0)
			{
				cout << "Send video stream packet failed!" << endl;
				av_strerror(iRes, errbuf, 256);
				return -5;
			}
			if ((iRes = avcodec_receive_frame(cctx, fr)) != 0)
			{
				cout << "Receive video frame failed!\n";
				av_strerror(iRes, errbuf, 256);
				return -6;
			}
			sws_scale(imgCtx, fr->data, fr->linesize, 0, cctx->height, yuv->data, yuv->linesize);

#ifdef _HZG_SDL_
			SDL_UpdateTexture(ste, &srect, yuv->data[0], yuv->linesize[0]);
			SDL_RenderClear(sr);
			SDL_RenderCopy(sr, ste, NULL, NULL);
			SDL_RenderPresent(sr);

			static bool s = false;
			if (!s)
			{
				s = true;
				int len = yuv->linesize[0] * cctx->height * 3;
				char* tmp = new char[len];
				char* des = new char[len];
				memcpy(tmp, (unsigned char*)yuv->data[0], len);


				
				AVFrame *tv = av_frame_alloc();
				av_image_fill_arrays(tv->data, tv->linesize, buf, AV_PIX_FMT_YUV420P, cctx->width, cctx->height, 1);

				//RotationRight90((unsigned char*)tmp, yuv->linesize[0], cctx->height, 3);

				yuv->height = cctx->height;
				yuv->width = yuv->linesize[0];

				char textM[100] = {0};
				sprintf(textM, "%d-%d-%d", yuv->linesize[0], yuv->linesize[1], yuv->linesize[2]);
				MessageBox(NULL, textM, "aa", 0);
				//Rotate90(yuv, tv);
				//frame_rotate_90WithSorrce(yuv, tv);
				//YUVRotate90((BYTE *)des, (BYTE *)tmp, yuv->width, yuv->height);

				//yuv_rotate_180_by_ssz((const char *)"yuv420p", yuv->width, yuv->height);
				//yuv_flip((const char *)"yuv420p", yuv->width, yuv->height);
				yuv_rotate_90_by_ssz((const char *)"yuv420p", yuv->width, yuv->height);
				//rotate90YUV420P((char *)"yuv420p", yuv->width, yuv->height);
				//saveImgFile((char*)tmp, vsize, "yuv420p-180.yuv");

				//saveImgFile((char*)des, yuv->width * yuv->height * 3, "yuv420p-ssz90-tv2.yuv");
				//saveImgFile((char*)tv->data[0], tv->linesize[0] * tv->height * 3, "yuv420p-ssz90-tv.yuv");
				//saveImgFile((char*)yuv->data[0], vsize, "yuv420p-1.5-vsize.yuv");
			}
			//Sleep(1);
#endif
		}
	}

	av_free(buf);
	av_frame_free(&yuv);
	av_frame_free(&fr);
	av_packet_free(&pkt);
	sws_freeContext(imgCtx);
#ifdef _HZG_SDL_
	SDL_DestroyTexture(ste);
	SDL_DestroyRenderer(sr);
	SDL_DestroyWindow(sw);
	SDL_Quit();
#endif
	avcodec_free_context(&cctx);
	avformat_close_input(&fctx);
	avformat_free_context(fctx);

	//////////////////////////////////////////////////////////////////////////





	// 主消息循環: 
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章