// sdltest1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
extern "C"
{
#include <SDL.h>
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/fifo.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavfilter/avfiltergraph.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
}
#include <memory>
#include <vector>
#include <windows.h>
#include <thread>
#include <mutex>
#include <queue>
#include <iostream>
#include "sdlplayer.h"
#pragma comment(lib, "avcodec.lib")
bool saveAsBitmap(AVFrame *pFrameRGB, int width, int height, int iFrame);
//int mymain();
//extern "C" _declspec(dllexport) int mymain();
int mymain(char* file);
//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
{
printf("come this -->\n");
if(argc!=2) {
printf("Args count not right!\n");
//return 0;
}
printf("%s \n",(char*)argv[1]);
mymain((char*)argv[1]);
//mymain();
return 0;
}
AVInputFormat mFormat;
AVDictionary* iformat_opts;
using namespace std;
#define INBUF_SIZE 4096
int videoIndex;
#define DelayTime 5
void Init()
{
av_register_all();
avfilter_register_all();
avformat_network_init();
av_log_set_level(AV_LOG_ERROR);
}
AVFormatContext *ic = NULL;
int64_t lastReadPacktTime ;
std::shared_ptr <AVPacket> readPacketFromSource()
{
std::shared_ptr<AVPacket> packet(static_cast<AVPacket*>(av_malloc(sizeof(AVPacket))), [&](AVPacket *p) { av_packet_free(&p); av_freep(&p);});
av_init_packet(packet.get());
lastReadPacktTime = av_gettime();
int ret = av_read_frame(ic, packet.get());
if(ret >= 0)
{
return packet;
}
else
{
return nullptr;
}
}
bool videoDecode(AVPacket* packet, AVFrame *frame)
{
int gotFrame = 0;
//videoIndex
auto hr = avcodec_decode_video2(ic->streams[videoIndex]->codec, frame, &gotFrame, packet);
if (hr >= 0 && gotFrame != 0)
{
return true;
}
return false;
}
int initVideoDecodeContext()
{
auto codecId = ic->streams[videoIndex]->codec->codec_id;
auto codec = avcodec_find_decoder(codecId);
if (!codec)
{
return -1;
}
int ret = avcodec_open2(ic->streams[videoIndex]->codec, codec, NULL);
return ret;
}
static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
char *filename)
{
FILE *f;
int i;
printf("filename = %s\n",filename);
f = fopen(filename,"w");
fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
for (i = 0; i < ysize; i++)
fwrite(buf + i * wrap, 1, xsize, f);
fclose(f);
}
int gWidth = 0;
int gHeight = 0;
int linesize[5] = { 640,320,320,0,0 };
typedef struct {
//BYTE buf[640*360*3/2+100];
std::shared_ptr<BYTE> buf;
BYTE* data[3];
int64_t dts;
} DecodeFrame;
//queue<DecodeFrame*> queFrame;
queue<std::shared_ptr<DecodeFrame>> queFrame;
int playState = 1;
std::shared_ptr<CGSDLRender> sdlRender;
mutex g_lock;
int64_t lastDts=0;
unsigned long lastTime = 0;
void playFun(){
for(;;){
if(playState == 0) break;
if (queFrame.size()>0){
g_lock.lock();
//DecodeFrame* dfr= queFrame.front();
std::shared_ptr<DecodeFrame> dfr= queFrame.front();
queFrame.pop();
g_lock.unlock();
auto diff = dfr->dts - lastDts;
int duration = diff * 1000 /(ic->streams[videoIndex]->time_base.den
/ic->streams[videoIndex]->time_base.num);
if(duration > DelayTime && duration < 1000){
Sleep(duration );
}
std::cout<<"duration1: "<<duration<<endl;
printf("packet->dts time =%d --->\n ", dfr->dts * 1000 / (ic->streams[videoIndex]->time_base.den
/ ic->streams[videoIndex]->time_base.num));
sdlRender->Display((char**)dfr->data,linesize);
lastDts = dfr->dts;
unsigned long nowTime = GetTickCount();
printf(" %ld cha %ld\n",nowTime,nowTime-lastTime); //得到ms
lastTime = nowTime;
//delete dfr;
}else{
Sleep(150);
}
}
}
int mymain(char* file)
{
int scan_all_pmts_set = 0;
/* register all codecs, demux and protocols */
Init();
ic = avformat_alloc_context();
int ret;
if (!ic) {
av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
ret = AVERROR(ENOMEM);
printf("alloc err %d\n",ret);
}
int err = avformat_open_input(&ic, "F://test.mp4", nullptr, nullptr);
//int err = avformat_open_input(&ic, "F://3s.mp4", nullptr, nullptr);
if (err < 0) {
printf("open err err=%d\n",err);
}
printf("come 2\n");
err = avformat_find_stream_info(ic, nullptr);
printf("ic->nb_streams %d\n",ic->nb_streams);
if(err<0){
}else{
for(int i=0;i<ic->nb_streams;i++){
int type = ic->streams[i]->codec->codec_type;
printf("type = %d\n",type);
if(type == AVMediaType::AVMEDIA_TYPE_VIDEO){
videoIndex = i;
printf("videoIndex =%d \n",videoIndex);
}
}
}
gWidth = ic->streams[videoIndex]->codec->width;
gHeight = ic->streams[videoIndex]->codec->height;
int ret1 =initVideoDecodeContext();
printf("ret1 = %d\n",ret1);
//std::shared_ptr<CGSDLRender>
sdlRender =std::make_shared<CGSDLRender>();//???????
ret = initVideoDecodeContext();
if(ret < 0) return ret;
sdlRender->InitVideo(0);
sdlRender->CreateVideoSurface(gWidth, gHeight);
AVRational time_base =ic->streams[videoIndex]->time_base;
printf("num %d,den %d--\n",time_base.num,time_base.den);
// to thi
playState = 1;
thread t1(playFun);
t1.detach();
int64_t lastDts=0;
int w = gWidth;
int h = gHeight;
AVFrame * videoFrame = av_frame_alloc();
for(int i=0;i<10000;i++){
auto packet = readPacketFromSource();
if(packet){
if(packet->stream_index==videoIndex){
if(videoDecode(packet.get(),videoFrame))
{
printf("%d---\n",i);
//printf("%lld \n",videoFrame->pkt_pos );
//DecodeFrame* dfr=&arrFrame[decodeFrame];
//DecodeFrame* dfr = new DecodeFrame;
std::shared_ptr<DecodeFrame> dfr(static_cast<DecodeFrame*>( new DecodeFrame), [&](DecodeFrame *p) { delete p;});
std::shared_ptr<BYTE> tmpbuf (new BYTE[w * h * 3 / 2 + 100](), std::default_delete<BYTE[]>());
dfr->buf = tmpbuf;
memcpy(dfr->buf.get(),videoFrame->data[0],w*h);
memcpy(dfr->buf.get() + w * h, videoFrame->data[1], w * h / 4);
memcpy(dfr->buf.get() + w * h * 5 / 4, videoFrame->data[2], w * h / 4);
dfr->data[0] = dfr->buf.get();
dfr->data[1] = dfr->buf.get() + w * h;
dfr->data[2] = dfr->buf.get() + w * h * 5 / 4;
dfr->dts = packet->dts;
g_lock.lock();
queFrame.push(dfr);
g_lock.unlock();
printf("packet->dts time =%d <---\n ",dfr->dts*1000/(ic->streams[videoIndex]->time_base.den
/ic->streams[videoIndex]->time_base.num));
if(queFrame.size()>30)
Sleep(100);
}
}
}
else{
break;
}
}
av_frame_free(&videoFrame);
//playFun();
Sleep(8000);
playState = 0;
Sleep(600);
system("PAUSE");
return 0;
}