#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;
}