Related
I am trying to capture and encode audio data, I am encoding audio using
FFMPEG AAC and to capture PCM data I used ALSA, Capturing part is working in my case, However, AAC encoder is not working.
I am trying to play test.aac file using
ffplay test.aac
but it contains lots of noise.
Attaching code for aac encoder :
#include "AudioEncoder.h"
void* AudioEncoder::run(void *ctx)
{
return ((AudioEncoder *)ctx)->execute();
}
static int frameCount = 0;
void* AudioEncoder::execute(void)
{
float buf[size], *temp;
int totalSize = 0;
int fd = open("in.pcm", O_CREAT| O_RDWR, 0666);
int frameSize = 128 * snd_pcm_format_width(SND_PCM_FORMAT_FLOAT) / 8 * 2;
av_new_packet(&pkt,size);
cout << size << endl;
while (!Main::stopThread)
{
temp = (Main::fbAudio)->dequeue();
memcpy(buf + totalSize, temp, frameSize);
write(fd, temp, frameSize); // Can play in.pcm with no noise in it.
totalSize += frameSize;
delete temp;
if (totalSize >= size)
{
totalSize = 0;
//frame_buf = (uint8_t *) buf;
pFrame->data[0] = (uint8_t *)buf; //PCM Data
pFrame->pts=frameCount;
frameCount++;
got_frame=0;
//Encode
ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame);
if(ret < 0){
cerr << "Failed to encode!\n";
return NULL;
}
if (got_frame==1){
printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size);
pkt.stream_index = audio_st->index;
#ifdef DUMP_TEST
ret = av_write_frame(pFormatCtx, &pkt);
#endif
av_free_packet(&pkt);
}
//memset(buf, 0, sizeof(float)*size);
}
//delete temp;
//if (buf.size() >= m_audio_output_decoder_ctx->frame_size)
/* encode the audio*/
}
close(fd);
Main::stopThread = true;
return NULL;
}
int AudioEncoder::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){
int ret;
int got_frame;
AVPacket enc_pkt;
if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
CODEC_CAP_DELAY))
return 0;
while (1) {
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_audio2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
NULL, &got_frame);
av_frame_free(NULL);
if (ret < 0)
break;
if (!got_frame){
ret=0;
break;
}
printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
/* mux encoded frame */
#ifdef DUMP_TEST
ret = av_write_frame(fmt_ctx, &enc_pkt);
if (ret < 0)
break;
#endif
}
return ret;
}
void AudioEncoder::start(void)
{
pthread_t encoder;
pthread_create(&encoder, NULL, &AudioEncoder::run, this);
}
AudioEncoder::AudioEncoder() : out_file("test.aac")
{
got_frame = 0;
ret = 0;
size = 0;
av_register_all();
avcodec_register_all();
//Method 1.
pFormatCtx = avformat_alloc_context();
fmt = av_guess_format(NULL, out_file, NULL);
pFormatCtx->oformat = fmt;
#ifdef DUMP_TEST
if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
cerr << "Failed to open output file!\n";
return;
}
#endif
audio_st = avformat_new_stream(pFormatCtx, 0);
if (audio_st==NULL){
return;
}
pCodecCtx = audio_st->codec;
pCodecCtx->codec_id = fmt->audio_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
pCodecCtx->sample_rate= 8000;
pCodecCtx->channel_layout=AV_CH_LAYOUT_STEREO;
pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
// pCodecCtx->bit_rate = 64000;
#ifdef DUMP_TEST
//Show some information
av_dump_format(pFormatCtx, 0, out_file, 1);
#endif
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec){
printf("Can not find encoder!\n");
return;
}
if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){
printf("Failed to open encoder!\n");
return;
}
pFrame = av_frame_alloc();
pFrame->nb_samples= pCodecCtx->frame_size;
pFrame->format= pCodecCtx->sample_fmt;
size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);
frame_buf = (uint8_t *)av_malloc(size);
avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);
//Write Header
#ifdef DUMP_TEST
avformat_write_header(pFormatCtx,NULL);
#endif
}
AudioEncoder::~AudioEncoder()
{
//Flush Encoder
ret = flush_encoder(pFormatCtx,0);
if (ret < 0) {
cerr << "Flushing encoder failed\n";
return;
}
#ifdef DUMP_TEST
//Write Trailer
av_write_trailer(pFormatCtx);
#endif
//Clean
if (audio_st){
avcodec_close(audio_st->codec);
av_free(pFrame);
av_free(frame_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
}
Here, please ignore DUMP_TEST flag, I already enabled it.
Can some one tell me what is issue ?
Thanks,
Harshil
I am able to resolve this issue, by correctly passing buffer from ALSA to AAC encoder.
Here AAC expects buffer size of 4096 bytes, but from deque I am passing 1024 bytes which causes issue, also I updated audio channels to MONO, in place of STEREO. Attaching my working code snippet for more information:
#include "AudioEncoder.h"
void* AudioEncoder::run(void *ctx)
{
return ((AudioEncoder *)ctx)->execute();
}
static int frameCount = 0;
void* AudioEncoder::execute(void)
{
float *temp;
#ifdef DUMP_TEST
int fd = open("in.pcm", O_CREAT| O_RDWR, 0666);
#endif
int frameSize = 1024 * snd_pcm_format_width(SND_PCM_FORMAT_FLOAT) / 8 * 1;
av_new_packet(&pkt,size);
while (!Main::stopThread)
{
temp = (Main::fbAudio)->dequeue();
frame_buf = (uint8_t *) temp;
pFrame->data[0] = frame_buf;
pFrame->pts=frameCount*100;
frameCount++;
got_frame=0;
//Encode
ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame);
if(ret < 0){
cerr << "Failed to encode!\n";
return NULL;
}
if (got_frame==1){
cout << "Encoded frame\n";
pkt.stream_index = audio_st->index;
#ifdef DUMP_TEST
write(fd, temp, frameSize);
ret = av_interleaved_write_frame(pFormatCtx, &pkt);
#endif
av_free_packet(&pkt);
}
delete temp;
}
#ifdef DUMP_TEST
close(fd);
#endif
Main::stopThread = true;
return NULL;
}
int AudioEncoder::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){
int ret;
int got_frame;
AVPacket enc_pkt;
if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
CODEC_CAP_DELAY))
return 0;
while (1) {
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_audio2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
NULL, &got_frame);
av_frame_free(NULL);
if (ret < 0)
break;
if (!got_frame){
ret=0;
break;
}
printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
/* mux encoded frame */
#ifdef DUMP_TEST
ret = av_write_frame(fmt_ctx, &enc_pkt);
if (ret < 0)
break;
#endif
}
return ret;
}
void AudioEncoder::start(void)
{
pthread_t encoder;
pthread_create(&encoder, NULL, &AudioEncoder::run, this);
}
AudioEncoder::AudioEncoder() : out_file("test.aac")
{
got_frame = 0;
ret = 0;
size = 0;
av_register_all();
avcodec_register_all();
//Method 1.
pFormatCtx = avformat_alloc_context();
fmt = av_guess_format(NULL, out_file, NULL);
pFormatCtx->oformat = fmt;
#ifdef DUMP_TEST
if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
cerr << "Failed to open output file!\n";
return;
}
#endif
audio_st = avformat_new_stream(pFormatCtx, 0);
if (audio_st==NULL){
return;
}
pCodecCtx = audio_st->codec;
pCodecCtx->codec_id = fmt->audio_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
pCodecCtx->sample_rate= 8000;
pCodecCtx->channel_layout=AV_CH_LAYOUT_MONO;
pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
pCodecCtx->bit_rate = 64000;
#ifdef DUMP_TEST
//Show some information
av_dump_format(pFormatCtx, 0, out_file, 1);
#endif
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec){
printf("Can not find encoder!\n");
return;
}
if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){
printf("Failed to open encoder!\n");
return;
}
pFrame = av_frame_alloc();
pFrame->nb_samples= pCodecCtx->frame_size;
pFrame->format= pCodecCtx->sample_fmt;
size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);
frame_buf = (uint8_t *)av_malloc(size);
avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);
//Write Header
#ifdef DUMP_TEST
avformat_write_header(pFormatCtx,NULL);
#endif
}
AudioEncoder::~AudioEncoder()
{
//Flush Encoder
ret = flush_encoder(pFormatCtx,0);
if (ret < 0) {
cerr << "Flushing encoder failed\n";
return;
}
#ifdef DUMP_TEST
//Write Trailer
av_write_trailer(pFormatCtx);
#endif
//Clean
if (audio_st){
avcodec_close(audio_st->codec);
av_free(pFrame);
av_free(frame_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
}
I'm working on an app in VC++ to display video frames of a video Pid of mpeg2ts stream using FFMPEG and need to do the same, for other mpeg2stream simultaneously by using multi thread process,my source code is:
int main (int argc, char* argv[])
{
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){
printf("Couldn't open input stream.\n");
return -1;
}
if(avformat_find_stream_info(pFormatCtx,NULL)<0){
printf("Couldn't find stream information.\n");
return -1;
}
videoindex=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
videoindex=i;
break;
}
if(videoindex==-1){
printf("Didn't find a video stream.\n");
return -1;
}
pCodecCtx=pFormatCtx->streams[videoindex]->codec;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL){
printf("Codec not found.\n");
return -1;
}
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){
printf("Could not open codec.\n");
return -1;
}
pFrame=av_frame_alloc();
pFrameYUV=av_frame_alloc();
out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
packet=(AVPacket *)av_malloc(sizeof(AVPacket));
//Output Info-----------------------------
printf("--------------- File Information ----------------\n");
av_dump_format(pFormatCtx,0,filepath,0);
printf("-------------------------------------------------\n");
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
#if OUTPUT_YUV420P
fp_yuv=fopen("output.yuv","wb+");
#endif
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
printf( "Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
screen_w = pCodecCtx->width;
screen_h = pCodecCtx->height;
//SDL 2.0 Support for multiple windows
screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h, SDL_WINDOW_OPENGL);
if(!screen) {
printf("SDL: could not create window - exiting:%s\n",SDL_GetError());
return -1;
}
sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
//IYUV: Y + U + V (3 planes)
//YV12: Y + V + U (3 planes)
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,pCodecCtx->width,pCodecCtx->height);
sdlRect.x=0;
sdlRect.y=0;
sdlRect.w=screen_w;
sdlRect.h=screen_h;
//SDL End----------------------
BYTE buffer [4] ;
int nSize = 0 ;
int nByteCnt = 0 ;
int nPreviuosPos = 0 ;
mpgfile = fopen ("D:\\00_Projects\\Farzan II\\SampleData\\Yahsat1996V_N_PID(2101).pes", "rb");
while(av_read_frame(pFormatCtx, packet)>=0 /*&& nSize > 0*/)
{
if(packet->stream_index==videoindex)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if(ret < 0)
{
printf("Decode Error.\n");
return -1;
}
if(got_picture)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameYUV->data, pFrameYUV->linesize);
#if OUTPUT_YUV420P
y_size=pCodecCtx->width*pCodecCtx->height;
fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y
fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U
fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V
#endif
//SDL---------------------------
#if 0
SDL_UpdateTexture( sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0] );
#else
SDL_UpdateYUVTexture(sdlTexture, &sdlRect,
pFrameYUV->data[0], pFrameYUV->linesize[0],
pFrameYUV->data[1], pFrameYUV->linesize[1],
pFrameYUV->data[2], pFrameYUV->linesize[2]);
#endif
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);
SDL_RenderPresent( sdlRenderer );
//SDL End-----------------------
//Delay 40ms
SDL_Delay(40);
}
}
av_free_packet(packet);
}
//flush decoder
//FIX: Flush Frames remained in Codec
while (1) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
break;
if (!got_picture)
break;
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameYUV->data, pFrameYUV->linesize);
#if OUTPUT_YUV420P
int y_size=pCodecCtx->width*pCodecCtx->height;
fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y
fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U
fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V
#endif
//SDL---------------------------
SDL_UpdateTexture( sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0] );
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);
SDL_RenderPresent( sdlRenderer );
//SDL End-----------------------
//Delay 40ms
SDL_Delay(40);
}
sws_freeContext(img_convert_ctx);
#if OUTPUT_YUV420P
fclose(fp_yuv);
#endif
SDL_Quit();
av_frame_free(&pFrameYUV);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
it works well when i call it in One thread but,after calling this function in multi thread ,the error of access violation occurred , is there anyone to guide me to solution?
so... context: I'm doing a layer 2 protocol for flexible forwarding in vehicular environment (for now my testbed is in virtual machines), this should take in consideration a different number of interfaces (for multihoming) and multihop.
So what I have:
A way of broadcasting hop-by-hop the service provider.
What I'm triyng to do:
A way to register a session all the way from the client to the provider (And here is the problem)
Problem: I have two types of packets
1st is listened correctly and data payload starts with a 1
2nd for some reason is not detected but I can see the packet is sent and correct with tcpdump
Since I have to register in the application the interface where the connection is made I used select() which seems to be part of the problem since I only guessed how it was used and I'm kind of in the dark about this.
UPDATED v3:
Okay so as soon as I removed most of the stuff about only sending on a specific interface all the stuff worked perfectly (I still need to clean this code... it's kind of messy). Here is code if someone is interested:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ifaddrs.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#define ETH_P_CUSTOM 0x0801 /* EtherType of Current Used Protocol*/
#define BUF_SIZE 1024
typedef enum {
false, true
} Bool; /* Boolean Definition*/
typedef struct Stat {
uint8_t maxSocket; /*Number of sockets to use in receive*/
uint8_t nInterfaces; /*Number of interfaces owned by this machine*/
uint8_t nSession; /*Number of Sessions Known in the linked list*/
uint8_t upMac[ETH_ALEN]; /*MAC of this host upstream parent*/
uint8_t nHops; /*Hops to Provider*/
char ifName[IF_NAMESIZE + 1]; /*Interface to Provider*/
} Stat;
typedef struct Node {
uint64_t session; /*Client Session*/
uint8_t nextHop[ETH_ALEN]; /*Next-Hop to Client*/
char ifName[IF_NAMESIZE + 1]; /*Outgoing Interface that connects to Next-Hop*/
struct Node * next; /*Next Session*/
} Node;
typedef struct ifNode {
uint8_t ifIndex; /*Interface index*/
uint8_t sock; /*Index in array of sockets*/
uint8_t mac[ETH_ALEN]; /*Interface MAC*/
char ifName[IF_NAMESIZE + 1]; /*Interface Name*/
struct ifNode * next; /*Next Session*/
} ifNode;
Stat * op; /* Variable which tracks status of certain structures/variables*/
Node * first = NULL, *last = NULL; /* Edges of linked list */
ifNode * iffirst = NULL, *iflast = NULL; /* Edges of interface linked list */
int cargc;
char **cargv;
int receiveP();
int broadServ();
int announceSelf();
Node* create(uint64_t sess, uint8_t n[ETH_ALEN], char interface[IF_NAMESIZE]);
void insert_node(Node * p);
Node* search(uint64_t session);
void update(uint64_t session, Node * p);
ifNode* createif(uint8_t idx, uint8_t sock, uint8_t ifmac[ETH_ALEN],
char interface[IF_NAMESIZE]);
void insert_ifnode(ifNode * p);
ifNode* searchif(uint8_t idx, uint8_t mode);
void updateif(uint8_t idx, ifNode * p);
void display();
void displayif();
void ctrlcoverride(int sig) {
printf("\nCtrl-C - Signal Caught - Exiting\n\n");
printf(
"Current Upstream MAC: %02x:%02x:%02x:%02x:%02x:%02x - NHops : %u - At Interface %s\n\n",
op->upMac[0], op->upMac[1], op->upMac[2], op->upMac[3],
op->upMac[4], op->upMac[5], op->nHops, op->ifName);
display();
exit(EXIT_SUCCESS);
}
Node* create(uint64_t sess, uint8_t n[ETH_ALEN], char interface[IF_NAMESIZE]) {
Node * new = (Node *) malloc(sizeof(Node));
if (new == NULL) {
printf("Could not create new node\n");
return NULL;
} else {
strcpy(new->ifName, interface);
new->session = sess;
int i;
for (i = 0; i < ETH_ALEN; i++)
new->nextHop[i] = n[i];
new->next = NULL;
return new;
}
}
ifNode* createif(uint8_t idx, uint8_t sock, uint8_t ifmac[ETH_ALEN],
char interface[IF_NAMESIZE]) {
ifNode * new = (ifNode *) malloc(sizeof(ifNode));
if (new == NULL) {
printf("Could not create new interface node\n");
return NULL;
} else {
new->ifIndex = idx;
new->sock = sock;
strcpy(new->ifName, interface);
int i;
for (i = 0; i < ETH_ALEN; i++)
new->mac[i] = ifmac[i];
new->next = NULL;
return new;
}
}
void insert_node(Node * p) {
if (first == last && last == NULL) {
first = last = p;
first->next = NULL;
last->next = NULL;
} else {
last->next = p;
last = last->next;
last->next = NULL;
}
}
void insert_ifnode(ifNode * p) {
if (iffirst == iflast && iflast == NULL) {
iffirst = iflast = p;
iffirst->next = NULL;
iflast->next = NULL;
} else {
iflast->next = p;
iflast = iflast->next;
iflast->next = NULL;
}
}
Node* search(uint64_t session) {
if (first == last && last == NULL) {
return NULL;
} else {
Node * temp;
for (temp = first; temp != NULL; temp = temp->next) {
if (temp->session == session) {
return temp;
}
}
return NULL;
}
}
ifNode* searchif(uint8_t idx, uint8_t mode) {
if (iffirst == iflast && iflast == NULL) {
return NULL;
} else {
ifNode * temp;
for (temp = iffirst; temp != NULL; temp = temp->next) {
if (temp->ifIndex == idx && mode == 0) {
return temp;
} else if (temp->sock == idx && mode == 1) {
return temp;
}
}
return NULL;
}
}
void update(uint64_t session, Node * p) {
if (first == last && last == NULL) {
return;
} else {
Node * temp;
for (temp = first; temp != NULL; temp = temp->next) {
if (temp->session == session) {
strcpy(temp->ifName, p->ifName);
temp->next = p->next;
int i;
for (i = 0; i < ETH_ALEN; i++)
temp->nextHop[i] = p->nextHop[i];
return;
}
}
}
}
void updateif(uint8_t idx, ifNode * p) {
if (iffirst == iflast && iflast == NULL) {
return;
} else {
ifNode * temp;
for (temp = iffirst; temp != NULL; temp = temp->next) {
if (temp->ifIndex == idx) {
strcpy(temp->ifName, p->ifName);
temp->sock = p->sock;
temp->next = p->next;
int i;
for (i = 0; i < ETH_ALEN; i++)
temp->mac[i] = p->mac[i];
return;
}
}
}
}
void display() {
Node * temp = first;
while (temp != NULL) {
printf("Session %" PRIu64 " Through %s - NextHop at ", temp->session,
temp->ifName);
int i;
for (i = 0; i < ETH_ALEN; i++)
printf("%02x ", temp->nextHop[i]);
printf("\n");
temp = temp->next;
}
}
void displayif() {
ifNode * temp = iffirst;
while (temp != NULL) {
printf("Interface Index %u Socket Number %u - Name %s with MAC: ",
temp->ifIndex, temp->sock, temp->ifName);
int i;
for (i = 0; i < ETH_ALEN; i++)
printf("%02x ", temp->mac[i]);
printf("\n");
temp = temp->next;
}
}
uint8_t counter() {
Node * temp = first;
uint8_t counter = 0;
while (temp != NULL) {
counter++;
temp = temp->next;
}
return counter;
}
fd_set rfds;
int rec;
int main(int argc, char **argv) {
setbuf(stdout, NULL);
signal(SIGINT, ctrlcoverride);
cargc = argc;
cargv = argv;
/*Setting Base Variables to Initial Values*/
op = (Stat*) malloc(sizeof(Stat));
op->nSession = 0;
memset(op->ifName, 0, IF_NAMESIZE);
op->maxSocket = 0;
op->nHops = UINT8_MAX - 1;
int i;
for (i = 0; i < ETH_ALEN; i++) {
op->upMac[i] = 0x00;
}
memset(&rfds, 0, sizeof(fd_set));
FD_ZERO(&rfds);
if (argc != 2) {
printf("USAGE: sudo %s {provider|node|nodekey}\n", cargv[0]);
exit(EXIT_FAILURE);
} else if (!(strcmp(cargv[1], "provider") == 0
|| strcmp(cargv[1], "node") == 0 || strcmp(cargv[1], "nodekey") == 0)) {
printf("USAGE: sudo %s {provider|node|nodekey}\n", cargv[0]);
exit(EXIT_FAILURE);
}
if (strcmp(cargv[1], "nodekey") == 0) {
srand(time(NULL));
uint8_t myArray[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
insert_node(
create((uint64_t) (100 * ((float) rand() / RAND_MAX)), myArray,
"SOURCE"));
}
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (ifa = ifaddr, op->nInterfaces = 0; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
if (ifa->ifa_addr->sa_family == AF_PACKET
&& strncmp(ifa->ifa_name, "lo", strlen("lo")) != 0
&& strncmp(ifa->ifa_name, "tap", strlen("tap")) != 0) {
op->nInterfaces++;
}
}
rec = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_CUSTOM));
int sockopt;
char ifName[IFNAMSIZ];
struct ifreq ifr;
for (i = 1, ifa = ifaddr; ifa != NULL;
ifa = ifa->ifa_next, i++) {
if (ifa->ifa_addr == NULL)
continue;
if (ifa->ifa_addr->sa_family == AF_PACKET
&& strncmp(ifa->ifa_name, "lo", strlen("lo")) != 0
&& strncmp(ifa->ifa_name, "tap", strlen("tap")) != 0) {
uint8_t sock;
if ((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_CUSTOM)))
== -1) {
printf("socket() error: %u - %s\n", errno, strerror(errno));
return EXIT_FAILURE;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt,
sizeof sockopt) == -1) {
printf("SO_REUSEADDR error: %u - %s\n", errno, strerror(errno));
close(sock);
return EXIT_FAILURE;
}
memset(&ifr, 0, sizeof(struct ifreq));
ifr.ifr_ifindex = i;
strcpy(ifr.ifr_name, ifa->ifa_name);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifa->ifa_name,
IF_NAMESIZE) == -1) {
printf("SO_BINDTODEVICE error: %u - %s\n", errno,
strerror(errno));
close(sock);
return EXIT_FAILURE;
}
struct sockaddr_ll sll;
sll.sll_family = AF_PACKET;
sll.sll_ifindex = i;
sll.sll_protocol = htons(ETH_P_CUSTOM);
if ((bind(sock, (struct sockaddr *) &sll, sizeof(sll))) == -1) {
perror("Error binding raw socket to interface\n");
exit(-1);
}
if ((ioctl(sock, SIOCGIFHWADDR, &ifr)) != 0) {
printf("SIOCGIFHWADDR error: %u - %s\n", errno,
strerror(errno));
return EXIT_FAILURE;
}
int j;
uint8_t ifmac[ETH_ALEN];
for (j = 0; j < ETH_ALEN; j++) {
ifmac[j] = (uint8_t) (ifr.ifr_hwaddr.sa_data)[j];
}
FD_SET(sock, &rfds);
op->maxSocket = (op->maxSocket < sock) ? sock : op->maxSocket;
insert_ifnode(createif(i, sock, ifmac, ifr.ifr_name));
}
}
displayif();
if (strcmp(cargv[1], "provider") == 0) {
struct ifreq if_mac; // interface
char * interface = "eth1";
int sockfd;
if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_CUSTOM))) == -1) {
printf("socket() error: %u - %s\n", errno, strerror(errno));
return EXIT_FAILURE;
}
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, interface, IFNAMSIZ - 1);
if ((ioctl(sockfd, SIOCGIFHWADDR, &if_mac)) != 0) {
printf("SIOCGIFHWADDR error: %u - %s\n", errno, strerror(errno));
return EXIT_FAILURE;
}
int i;
for (i = 0; i < ETH_ALEN; i++)
op->upMac[i] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[i];
op->nHops = 0;
close(sockfd);
}
freeifaddrs(ifaddr);
int stat = 0;
while (1) {
if (strcmp(cargv[1], "provider") == 0) {
if ((stat = receiveP()) != 0)
return stat;
if ((stat = broadServ()) != 0)
return stat;
display();
usleep(100000);
} else if (strcmp(cargv[1], "node") == 0
|| strcmp(cargv[1], "nodekey") == 0) {
if ((stat = receiveP()) != 0)
return stat;
if ((stat = announceSelf()) != 0){
return stat;
}
if ((stat = broadServ()) != 0)
return stat;
display();
usleep(100000);
}
}
ifNode * temp = iffirst;
while (temp != NULL) {
close(temp->sock);
temp = temp->next;
}
exit(stat);
}
int receiveP() {
int stat = 0;
struct ifreq ifr;
struct sockaddr saddr;
long unsigned int numbytes = 0;
char buf[BUF_SIZE];
memset(buf, 0, BUF_SIZE);
struct ether_header *eh = (struct ether_header *) buf;
unsigned int saddr_size = sizeof saddr;
struct timeval tv;
tv.tv_sec = 3; /* 3 Secs Timeout */
tv.tv_usec = 0;
setsockopt(rec, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv,
sizeof(struct timeval));
numbytes = recvfrom(rec, buf, BUF_SIZE, 0, &saddr, &saddr_size);
int len;
int ntable;
switch (buf[sizeof(struct ether_header)]) {
case 1:
if (buf[sizeof(struct ether_header) + 1] < op->nHops) {
op->upMac[0] = eh->ether_shost[0];
op->upMac[1] = eh->ether_shost[1];
op->upMac[2] = eh->ether_shost[2];
op->upMac[3] = eh->ether_shost[3];
op->upMac[4] = eh->ether_shost[4];
op->upMac[5] = eh->ether_shost[5];
op->nHops = buf[sizeof(struct ether_header) + 1] + 1;
memset(&ifr, 0, sizeof(struct ifreq));
memset(&ifr.ifr_name, 0, IF_NAMESIZE);
printf(
"Server %u Hops Away - Through %02x:%02x:%02x:%02x:%02x:%02x At Interface %s\n",
op->nHops, eh->ether_shost[0], eh->ether_shost[1],
eh->ether_shost[2], eh->ether_shost[3], eh->ether_shost[4],
eh->ether_shost[5], op->ifName);
printf("\n\n");
}
break;
case 2:
len = sizeof(struct ether_header) + 1;
ntable = buf[len++];
int j;
for (j = 0; j < ntable; j++, len++) {
if (search(buf[len]) == NULL) {
insert_node(create(buf[len], eh->ether_shost, ""));
}
}
break;
}
return stat;
}
int broadServ() {
int stat = 0;
int tx_len = 0;
char sendbuf[BUF_SIZE];
char ifName[IF_NAMESIZE - 1];
struct ether_header *eh = (struct ether_header *) sendbuf;
struct sockaddr_ll socket_address;
int i;
struct ifreq ifr, if_mac;
ifNode * temp = iffirst;
while (temp != NULL) {
/* Get the index of the interface to send on */
memset(&ifr, 0, sizeof(struct ifreq));
ifr.ifr_ifindex = temp->ifIndex;
if (ioctl(temp->sock, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFINDEX");
memset(ifName, 0, IF_NAMESIZE - 1);
strncpy(ifName, ifr.ifr_name, IF_NAMESIZE - 1);
/* Get the MAC address of the interface to send on */
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, ifName, IFNAMSIZ - 1);
if (ioctl(temp->sock, SIOCGIFHWADDR, &if_mac) < 0)
perror("SIOCGIFHWADDR");
if (((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[0] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[1] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[2] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[3] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[4] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[5] == 0x00)
continue;
memset(sendbuf, 0, BUF_SIZE);
/* Ethernet header */
eh->ether_shost[0] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[0];
eh->ether_shost[1] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[1];
eh->ether_shost[2] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[2];
eh->ether_shost[3] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[3];
eh->ether_shost[4] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[4];
eh->ether_shost[5] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[5];
eh->ether_dhost[0] = 0xff;
eh->ether_dhost[1] = 0xff;
eh->ether_dhost[2] = 0xff;
eh->ether_dhost[3] = 0xff;
eh->ether_dhost[4] = 0xff;
eh->ether_dhost[5] = 0xff;
/* Ethertype field */
eh->ether_type = htons(ETH_P_CUSTOM);
tx_len = sizeof(struct ether_header);
/* Packet data */
sendbuf[tx_len++] = 1;
sendbuf[tx_len++] = op->nHops; //+1;
/* Index of the network device */
socket_address.sll_ifindex = temp->ifIndex;
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = 0xff;
socket_address.sll_addr[1] = 0xff;
socket_address.sll_addr[2] = 0xff;
socket_address.sll_addr[3] = 0xff;
socket_address.sll_addr[4] = 0xff;
socket_address.sll_addr[5] = 0xff;
/* Send packet */
if (sendto(temp->sock, sendbuf, tx_len, 0,
(struct sockaddr*) &socket_address, sizeof(struct sockaddr_ll))
< 0)
printf("Send failed\n");
temp = temp->next;
}
return stat;
}
int announceSelf() {
if (op->upMac[0] == 0x00 && op->upMac[1] == 0x00 && op->upMac[2] == 0x00
&& op->upMac[3] == 0x00 && op->upMac[4] == 0x00
&& op->upMac[5] == 0x00)
return EXIT_SUCCESS;
int stat = 0;
int tx_len = 0;
char sendbuf[BUF_SIZE];
char ifName[IF_NAMESIZE - 1];
struct ether_header *eh = (struct ether_header *) sendbuf;
struct sockaddr_ll socket_address;
int i;
struct ifreq ifr, if_mac;
ifNode * temp = iffirst;
while (temp != NULL) {
memset(&ifr, 0, sizeof(struct ifreq));
ifr.ifr_ifindex = temp->ifIndex;
if (ioctl(temp->sock, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFINDEX");
memset(ifName, 0, IF_NAMESIZE - 1);
strncpy(ifName, ifr.ifr_name, IF_NAMESIZE - 1);
/* Get the MAC address of the interface to send on */
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, ifName, IFNAMSIZ - 1);
if (ioctl(temp->sock, SIOCGIFHWADDR, &if_mac) < 0)
perror("SIOCGIFHWADDR");
if (((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[0] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[1] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[2] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[3] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[4] == 0x00
&& ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[5] == 0x00)
continue;
memset(sendbuf, 0, BUF_SIZE);
/* Ethernet header */
eh->ether_shost[0] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[0];
eh->ether_shost[1] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[1];
eh->ether_shost[2] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[2];
eh->ether_shost[3] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[3];
eh->ether_shost[4] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[4];
eh->ether_shost[5] = ((uint8_t *) &if_mac.ifr_hwaddr.sa_data)[5];
eh->ether_dhost[0] = op->upMac[0];
eh->ether_dhost[1] = op->upMac[1];
eh->ether_dhost[2] = op->upMac[2];
eh->ether_dhost[3] = op->upMac[3];
eh->ether_dhost[4] = op->upMac[4];
eh->ether_dhost[5] = op->upMac[5];
/* Ethertype field */
eh->ether_type = htons(ETH_P_CUSTOM);
tx_len = sizeof(struct ether_header);
/* Packet data */
sendbuf[tx_len++] = 2;
sendbuf[tx_len++] = counter();
Node *temp1 = first;
for (; temp1 != NULL; temp1 = temp1->next) {
sendbuf[tx_len++] = temp1->session;
}
socket_address.sll_ifindex = temp->ifIndex;
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = op->upMac[0];
socket_address.sll_addr[1] = op->upMac[1];
socket_address.sll_addr[2] = op->upMac[2];
socket_address.sll_addr[3] = op->upMac[3];
socket_address.sll_addr[4] = op->upMac[4];
socket_address.sll_addr[5] = op->upMac[5];
/* Send packet */
if (sendto(temp->sock, sendbuf, tx_len, 0,
(struct sockaddr*) &socket_address, sizeof(struct sockaddr_ll))
< 0)
printf("Send failed\n");
temp = temp->next;
}
return stat;
}
So to test this you can have VM with linux connected like this (for example):
Provider ----- Node ----- Node ----- Nodekey
I still had a problem when creating multiple sessions, i wasn't incrementing the buffer when reading and I was reading multiple times the same position. Now it's working good
OK, let's begin with the easiest recommendations but I'm not sure this is going to resolve the problem at once. I did a system like this many years ago for different boards with different processor architectures communicating with each other. All the boards were running within a telecommunication switch. It's a very nice problem and you are facing it in the proper way with a peer-to-peer distributed solution.
I didn't go through all code but it seems each node is discovering the neighbour nodes in the network and everyone is creating a tree.
In select, the first argument should not be FD_SETSIZE but the highest-numbered file descriptor in any of the three sets (in this case the read set), plus 1.
The infinite loop is calling receiveSession which is creating all sockets again and then it reads. If a frame with your specific layer-2 protocol arrives in the middle and there is no socket listening for it, it will be discarded. Maybe your problem could be here.
When you send Ethernet frames directly, the hardware will complete the frame to the minimum Ethernet size: 64 octets (so you might receive padding data up to 46 octets - Octets not Bytes)
Please read here:
http://en.wikipedia.org/wiki/Ethernet_frame
It is good you chose an EtherType ETH_P_CUSTOM higher than 1536 that is not already in use but maybe you want to use a much higher number in order to minimize possibilities of collision with other protocols.
Something important. Your testbed now is with VM's which are usually x86 architectures, 64 bits. When you run your software in real devices with different processors, that might not be the situation. This is very important because you might have different architectures with different endianship and different integer size. That will affect the integer numbers you send, especially in ether_header, and the size of your structures. You have to use the the macros ntohs, ntohl, htons, htonl to change between host and network endianship (session is uint64_t). You should send data in network endianship. This is not solving your very current problem but you might have this problem in the future.
I try to send some data from user mode to my kernel module. But when it send something, it triggers a kernel error:
Bug:unable to handle kernel paging request ad ffff88022f168bc0
IP: [<...>]build_skb+0xf5/0x1c0
#include "socket.hpp"
using namespace std;
KernelSocket::KernelSocket(DataLink * dl){
this->dl = dl;
this->sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0) {
printf("unable to create socket%d\n", sock_fd);
exit(-1);
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
//src_addr.nl_groups = 0;
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
reportLocalAddress();
}
void KernelSocket::sendToKernel(string data){
int length = data.length();
char c;
c = (length%0xff);
data.insert(0, 1, c);
c = (length/0xff);
data.insert(0, 1, c);
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
memcpy((NLMSG_DATA(nlh)), data.c_str(), length+2);
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
//iov.iov_len = length;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock_fd,&msg,0);
}
void KernelSocket::reportLocalAddress(){
int length = 6;
string data = dl->localAddress.toString();
data.insert(0,1, 0xff);
data.insert(0,1, 0xff);
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
memcpy((NLMSG_DATA(nlh)), data.c_str(), length+2);
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock_fd,&msg,0);
printf("send mac address to kernel\n");
}
void * kernelSocketWorkLoop(void * kernelSocket){
int length,ret;
KernelSocket * ks = (KernelSocket *) kernelSocket;
while(1){
ret = recvmsg(ks->sock_fd, &(ks->msg), MSG_DONTWAIT);
if(ret>=0){
string c;
c.assign((char *)NLMSG_DATA(ks->nlh));
length = c[0]*0xff+c[1];
ks->dl->packetDownBuffer.push(c);
}
sleep(1);
}
}
I am using this period code now. Anybody have opinion on this problem? Thanks~
Here is the function in the kernel module that I use to receive message.
static void ss_recv(struct sk_buff *skb){
struct nlmsghdr *nlh;
int len;
char * c;
struct uwmodem_priv* priv = NULL;
priv = netdev_priv(dev);
printk("in ss_recv\n");
nlh = (struct nlmsghdr *)skb->data;
if(nlh->nlmsg_pid>0){
priv->daemon_pid = nlh->nlmsg_pid;
len = nlh->nlmsg_len - NLMSG_HDRLEN;
c = kmalloc(len, GFP_ATOMIC);
if(c==NULL){
printk("Fail to allocate c\n");
}
memcpy(c, nlmsg_data(nlh), len);
if(c[0]==0xff && c[1]==0xff){
printk("Set MacAddress(%d) \n", nlh->nlmsg_pid);
//for mac address
memcpy(dev->dev_addr, c+2, ETH_ALEN);
}else{
len = c[0]*0xff+c[1];
//printk("Kernel Length:[%d][%d][%d]\n", c[0], c[1], c[2]);
printk("Kernel received from (%d)[%d]: \n", nlh->nlmsg_pid,len);
uwmodem_rx(dev, c+2, len);
}
kfree(c);
}
//printk("Exit ss_recv\n");
}
I am trying to encode a stream buffer of frames grabbed by ISampleGrabber(directshow) by using libavcodec. After encoding those frame I am writing it into a file. But after completion file contains only green frames.
hers is code for grabbing frames and encoding it...
void DSGrabberCallback::initFFMpeg(){
const char* filename="G:/test1.mpg";
avcodec_register_all();
printf("Encode video file %s\n", filename);
AVCodecID codec_id=AV_CODEC_ID_MPEG2VIDEO;
codec = avcodec_find_encoder(codec_id);
c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate video codec context\n");
}
c->bit_rate = 4000000;
c->width = 320;
c->height = 240;
AVRational test;
test.den=25;
test.num=1;
c->time_base= test;
c->gop_size = 10;
//c->max_b_frames=1;
c->pix_fmt = AV_PIX_FMT_YUV420P;
if(codec_id == AV_CODEC_ID_H264)
av_opt_set(c->priv_data, "preset", "slow", 0);
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
}
f = fopen(filename, "wb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
}
picture = alloc_picture(c->pix_fmt, c->width, c->height);
/*picture->format = c->pix_fmt;
picture->width = c->width;
picture->height = c->height;*/
av_init_packet(&pkt);
}
void DSGrabberCallback::encodeFrame(unsigned char *frame,ULONG size){
std::cout<<"called.....";
pkt.data = NULL;
pkt.size = 0;
picture->data[0]=frame;
fflush(stdout);
picture->pts=counter;
ret = avcodec_encode_video2(c, &pkt, picture, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding frame\n");
}
if (got_output) {
printf("Write frame %3d (size=%5d)\n", counter, pkt.size);
fwrite(pkt.data, 1, pkt.size, f);
av_free_packet(&pkt);
}
}
STDMETHODIMP DSGrabberCallback::SampleCB(double time, IMediaSample* sample)
{
BYTE* data = NULL;
ULONG length = 0;
m_bytes=NULL;
counter=counter+1;
if(FAILED(sample->GetPointer(&data)))
{
return E_FAIL;
}
length = sample->GetActualDataLength();
if(length == 0)
{
return S_OK;
}
if(!m_bytes || m_bytesLength < length)
{
if(m_bytes)
{
delete[] m_bytes;
}
m_bytes = new unsigned char[length];
m_bytesLength = length;
}
if(true)
{
for(size_t row = 0 ; row < 480 ; row++)
{
memcpy((m_bytes + row * 640 * 2), data + (480 - 1 - row) * 640 * 2,
640 * 2);
}
}
std::cout<<"hiiiiiiiiiiiiiiiiiiiiiiii";
// memcpy(m_bytes, data, length);
// std::cout<<"called............... "<<m_bytes<<"\n";
if(counter<500){
encodeFrame(m_bytes,length);
}else{
fwrite(endcode, 1, sizeof(endcode), f);
fclose(f);
avcodec_close(c);
av_free(c);
av_freep(&picture->data[0]);
avcodec_free_frame(&picture);
printf("\n");
exit(1);
}
//rtp.sendRTP(data,length);
//sample->Release();
//printf("Sample received: %p %u\n", data, length);
return S_OK;
}
can anyone tell me where is the problem.
Now working fine. Actually I forgot to convert the image buffer into YUV420P format. I have added some code for scaling the buffer into YUV format and everything is fine now. Thank you Wimmel and Roman R.