#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
// for cross compatibility
typedef unsigned int IN_PORT;
typedef unsigned short IN_FAMILY;
typedef unsigned long IN_ADDR_T;
#ifdef WIN32
#include <winsock2.h>
#include <stdint.h>
#elif defined (linux)
// the goal of these definitions is to use the same names both in Windows and Linux
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> /* close */
#include <netdb.h> /* gethostbyname */
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
// here we are defining a macro in order to invoke the function to close a socket with the same name
#define closesocket(s) close(s) //In windows closesocket(Socket) and linux it is close(Socket)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
/*
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
*/
typedef struct in_addr IN_ADDR;
#else
#error not defined for this platform
#endif
static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame);
static void fillPacket(AVPacket *streamPacket, uint8_t *packet, size_t size);
static void SendFrame(uint8_t *packet, size_t size);
int main (int argc, const char * argv[])
{
AVFormatContext *pFormatCtx;
int i, videoStream, audioStream, iaudio, ivideo, videoFrames;
AVCodecContext *pCodecCtx, *audioCodecCtx;
AVCodec *pCodec, *audioCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
uint8_t *packet_buffer;
uint8_t *outbuf;
size_t packet_size;
// Register all formats and codecs
av_register_all();
// Open video file
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
return -1; // Couldn't open file
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
return -1; // Couldn't find stream information
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, argv[1], false);
// Find the first video stream and the first audio stream
videoStream = audioStream = -1;
for(i=0; i<pFormatCtx->nb_streams; i++) {
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
{
videoStream = i;
//break;
} else if (pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
audioStream = i;
}
}
if(videoStream==-1)
return -1; // Didn't find a video stream
if(audioStream==-1)
return -1; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Get a pointer to the codec context for the audio stream
audioCodecCtx=pFormatCtx->streams[audioStream]->codec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
return -1; // Codec not found
// Find the decoder for the audio stream
audioCodec=avcodec_find_decoder(audioCodecCtx->codec_id);
if(audioCodec==NULL)
return -1; // Codec not found
// Open codec for the video stream
if(avcodec_open(pCodecCtx, pCodec)<0)
return -1; // Could not open codec
// Open codec for the audio stream
if(avcodec_open(audioCodecCtx, audioCodec)<0)
return -1; // Could not open codec
// Hack to correct wrong frame rates that seem to be generated by some codecs
if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)
pCodecCtx->time_base.den=1000;
// Allocate video/audio frame
pFrame=avcodec_alloc_frame();
//outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return -1;
printf("%d pFrame Size = %d pFrameRGB size = %d\n", sizeof(AVFrame), sizeof(*pFrame), sizeof(*pFrameRGB));
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer=malloc(numBytes);
packet_buffer = NULL;
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i = iaudio = ivideo = packet_size = videoFrames = 0;
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
printf("#%d Video packet found: size is %d\n", i, packet.size);
// Decode video frame
/*avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if(frameFinished)
{
static struct SwsContext *img_convert_ctx;
// Convert the image into YUV format that SDL uses
if(img_convert_ctx == NULL) {
int w = pCodecCtx->width;
int h = pCodecCtx->height;
img_convert_ctx = sws_getContext(w, h,
pCodecCtx->pix_fmt,
w, h, PIX_FMT_RGB24, SWS_BICUBIC,
NULL, NULL, NULL);
if(img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
}
int ret = sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
}*/
i++;
ivideo++;
videoFrames++;
} else {
printf("#%d Audio packet found: size is %d\n", i, packet.size);
// Decode audio frame
/*int outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
avcodec_decode_audio2(audioCodecCtx, (short *)outbuf, &outsize, packet.data, packet.size);*/
i++;
iaudio++;
}
//if (packet.stream_index==videoStream) {
packet_size += packet.size;
printf("i modulo 7 is %d size of packet is %d packet_size is %d\n", i%7, packet.size, packet_size);
if (packet_buffer != NULL) {
packet_buffer = realloc(packet_buffer, packet_size);
} else {
packet_buffer = malloc(packet_size);
}
//printf("DONE\n");
fillPacket(&packet, packet_buffer, packet_size);
if (i % 7 == 0) {
printf("%d Sending a UDP packet\n", (int)(i/7));
SendFrame(packet_buffer, packet_size);
usleep(40000*videoFrames);
//free(packet_buffer);
packet_size = 0;
videoFrames = 0;
}
//}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
printf("%d packets: %d video %d audio\n", i, ivideo, iaudio);
//free(outbuf);
// Free the RGB image
free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
return 0;
}
void fillPacket(AVPacket *streamPacket, uint8_t *packet, size_t size)
{
memcpy(packet+size-streamPacket->size, streamPacket->data, streamPacket->size);
}
void SendFrame (uint8_t *packet, size_t size)
{
// socket creation
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN sin;
char address[10] = "127.0.0.1";
struct hostent *hostinfo;
if(sock == INVALID_SOCKET)
{
perror("socket()");
exit(errno);
}
hostinfo = gethostbyname(address);
if (hostinfo == NULL)
{
fprintf (stderr, "Unknown host %s.\n", address);
exit(EXIT_FAILURE);
}
sin.sin_addr = *(IN_ADDR *) hostinfo->h_addr;
sin.sin_port = htons(2500);
sin.sin_family = AF_INET;
sendto(sock, packet, size, 0, (SOCKADDR *) &sin, sizeof(sin));
closesocket(sock);
/*FILE *pFile;
char szFilename[32];
int y;
// Open file
sprintf(szFilename, "prova.ts");
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;
// Write header
//fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
//for(y=0; y<height; y++)
//fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
fwrite(packet->data, packet->size, 1, pFile);
// Close file
fclose(pFile);*/
}
static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
/*FILE *pFile;
char szFilename[32];
int y;
// Open file
sprintf(szFilename, "video/frames/frame%d.ppm", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;
// Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
for(y=0; y<height; y++)
fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
// Close file
fclose(pFile);*/
}