From 067f68c8c6118e9f9241e4f0eb872aad4888dba0 Mon Sep 17 00:00:00 2001 From: deva Date: Wed, 13 Apr 2005 14:05:29 +0000 Subject: decoder rewritten for input throgh raw1394 instead of dv1394 (kernel bug in 2.6.x) --- TODO | 4 +- configure.in | 5 +- src/debug.h | 73 +++++++++++++++++++++++ src/decoder.cc | 166 ++++++++++++++++++++++++++++++++++++++++++++++------- src/dvframe.cc | 2 - src/ffframe.cc | 6 +- src/img_encoder.cc | 12 ++-- src/miav.cc | 2 + src/mov_encoder.cc | 14 +++-- 9 files changed, 246 insertions(+), 38 deletions(-) diff --git a/TODO b/TODO index 7e9ff73..0ca8020 100644 --- a/TODO +++ b/TODO @@ -67,10 +67,12 @@ Makesystem: [x] - Make server standalone compilable (through flag to configure) [x] - Include pixmaps and tools in distdir. [x] - Make pixmaps correctly intalled. - [ ] - Make QT link correctly on fedora core 1 + [x] - Make QT link correctly on fedora core 1 + [ ] - Make libJpeg link correctly on fedora core 1 MiavConfig: [x] - Integrate file parser. + [x] - USe error object. [ ] - Make code for input validity test. ErrorObject: diff --git a/configure.in b/configure.in index d53a1aa..333557a 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ # Filename: configure.in AC_INIT(src/miav.cc) -AM_INIT_AUTOMAKE( miav, 0.1.1 ) +AM_INIT_AUTOMAKE( miav, 0.1.2 ) AC_PROG_CXX @@ -28,6 +28,9 @@ if test x$with_gui != xno && test -z "$GUI"; then CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" LDFLAGS="$LDFLAGS $SDL_LIBS" + AC_CHECK_HEADER(libraw1394/raw1394.h, , AC_MSG_ERROR([*** libraw1394 headers not found!])) + AC_CHECK_LIB(raw1394, raw1394_get_userdata, , AC_MSG_ERROR([*** libraw1394 not found!])) + dnl Make code aware of the gui AC_DEFINE([USE_GUI], [], [Is defined if the project is configured to compile with gui]) else diff --git a/src/debug.h b/src/debug.h index 4940393..34cfeee 100644 --- a/src/debug.h +++ b/src/debug.h @@ -26,4 +26,77 @@ #include #ifndef __MIAV_DEBUG_H__ #define __MIAV_DEBUG_H__ + +//#define DEBUG_ALLOC + +#ifdef DEBUG_ALLOC +typedef struct _A_{ + struct _A_* prev; + struct _A_* next; + char name[32]; + void *addr; +} __debug__; + +__debug__ *debug_first = NULL; + +inline void debugAlloc(void *p, char* name) +{ + __debug__ *d = debug_first; + + fprintf(stderr, "Adding %d - %s\n", p, name); + + debug_first = (__debug__*)malloc(sizeof(__debug__)); + debug_first->prev = NULL; + debug_first->next = d; + if(d) d->prev = debug_first; + debug_first->addr = p; + strcpy(debug_first->name, name); +} + +inline void debugFree(void *p) +{ + __debug__ *d = debug_first; + + while(d && d->addr != p) { + d = d->next; + } + + if(!d) { + fprintf(stderr, "ERROR: memory address not found %d - perhaps already freed!\n", p); + exit(1); + } + + fprintf(stderr, "Removing %d - %s\n", p, d->name); + __debug__ *next = d->next; + __debug__ *prev = d->prev; + if(prev) prev->next = d->next; + if(next) next->prev = d->prev; + if(debug_first == d) debug_first = next; + free(d); +} + +inline void debugPrint() +{ + __debug__ *d = debug_first; + + fprintf(stderr, "Alloc List:\n"); + + while(d) { + fprintf(stderr, "\t[%d] %s\n", d->addr, d->name); + d = d->next; + } +} + +#define FREE(x) debugFree(x) +#define ALLOC(x, y) debugAlloc(x, y) +#define PRINT() debugPrint() + +#else/*DEBUG_ALLOC*/ + +#define FREE(x) {} +#define ALLOC(x, y) {} +#define PRINT() {} + +#endif/*DEBUG_ALLOC*/ + #endif/*__MIAV_DEBUG_H__*/ diff --git a/src/decoder.cc b/src/decoder.cc index c7a4e50..fcbf136 100644 --- a/src/decoder.cc +++ b/src/decoder.cc @@ -22,8 +22,15 @@ */ #include #ifdef USE_GUI - +#include +#include +#include +#include +#include #include "decoder.h" +#include "debug.h" + +static AVCodecContext mycodec; Decoder::Decoder(Error* err, char *device, @@ -36,7 +43,7 @@ Decoder::Decoder(Error* err, volatile int *grunning) { errobj = err; - +device = ""; encode_sem = gencode_sem; player_sem = gplayer_sem; encode_queue = gencode_queue; @@ -49,6 +56,7 @@ Decoder::Decoder(Error* err, AVInputFormat *iformat; AVCodec *dec_codec; +/* memset(&dvpars, 0, sizeof(dvpars)); if(!(iformat = av_find_input_format("dv1394"))) { @@ -57,30 +65,33 @@ Decoder::Decoder(Error* err, return; } - dvpars.device = device; /* "/dev/dv1394"; */ + dvpars.device = device; // "/dev/dv1394"; dvpars.channel = channel; dvpars.standard = "pal"; - - if(av_open_input_file(&ifc, "", iformat, 0, &dvpars) < 0) { + memset(&dvpars, 0, sizeof(dvpars)); + dvpars.device = ""; + int err1; + if((err1 = av_open_input_file(&ifc, "file:///root/dvgrab-001.dv", iformat, 0, &dvpars)) < 0) { +fprintf(stderr, "Error in open: %d\n", err1); errobj->pushError("Device is in use."); fc = NULL; - return; +// return; } if(av_find_stream_info(ifc) < 0) { errobj->pushError("Could not find enough parameters."); fc = NULL; - return; +// return; } dump_format(ifc, 1, "", 0); - - if(!(dec_codec = avcodec_find_decoder(ifc->streams[0]->codec.codec_id))) { +*/ + if(!(dec_codec = avcodec_find_decoder(CODEC_ID_DVVIDEO/*ifc->streams[0]->codec.codec_id*/))) { errobj->pushError("Unsupported codec for input stream."); fc = NULL; return; } - if(avcodec_open(&ifc->streams[0]->codec, dec_codec) < 0) { + if(avcodec_open(&mycodec/*&ifc->streams[0]->codec*/, dec_codec) < 0) { errobj->pushError("Error while opening codec for input stream."); fc = NULL; return; @@ -95,22 +106,134 @@ Decoder::~Decoder() av_close_input_file(fc); } +static int raw_reader( raw1394handle_t handle, int channel, size_t length, quadlet_t *data ) +{ + /* skip empty packets */ + static char *framedata = NULL; +//printf("raw_reader\n"); fflush(stdout); + if ( length > 16 ) + { + unsigned char * p = ( unsigned char* ) & data[ 3 ]; + int section_type = p[ 0 ] >> 5; /* section type is in bits 5 - 7 */ + int dif_sequence = p[ 1 ] >> 4; /* dif sequence number is in bits 4 - 7 */ + int dif_block = p[ 2 ]; + + /* if we are at the beginning of a frame, we put the previous + frame in our output_queue. Then we try to get an unused + frame_buffer from the buffer_queue for the current frame. + We must lock the queues because they are shared between + this thread and the main thread. */ + if ( section_type == 0 && dif_sequence == 0 ) + { + if ( framedata != NULL ) + { + raw1394_set_userdata(handle, (void *)framedata); + framedata = NULL; + } + } + + if(!framedata) + { + framedata = (char *)malloc(DVPACKAGE_SIZE); // dvframe.h + if(!framedata) + { + /* We're fucked */ + exit(1); + } + } + + switch ( section_type ) + { + case 0: /* 1 Header block */ + /* p[3] |= 0x80; // hack to force PAL data */ + memcpy( framedata + dif_sequence * 150 * 80, p, 480 ); + break; + + case 1: /* 2 Subcode blocks */ + memcpy( framedata + dif_sequence * 150 * 80 + ( 1 + dif_block ) * 80, p, 480 ); + break; + + case 2: /* 3 VAUX blocks */ + memcpy( framedata + dif_sequence * 150 * 80 + ( 3 + dif_block ) * 80, p, 480 ); + break; + + case 3: /* 9 Audio blocks interleaved with video */ + memcpy( framedata + dif_sequence * 150 * 80 + ( 6 + dif_block * 16 ) * 80, p, 480 ); + break; + + case 4: /* 135 Video blocks interleaved with audio */ + memcpy( framedata + dif_sequence * 150 * 80 + ( 7 + ( dif_block / 15 ) + dif_block ) * 80, p, 480 ); + break; + + default: /* we canĀ“t handle any other data */ + break; + } + } + return 0; +} + + void Decoder::decode() { + int port = 0; + int channel = 63; + int n_ports; + struct raw1394_portinfo pinf[ 16 ]; + raw1394handle_t handle; + handle = raw1394_new_handle(); + if ( !handle ) + { + fprintf( stderr, "raw1394 - failed to get handle: %s.\n", strerror( errno ) ); + exit( EXIT_FAILURE ); + } + + if ( ( n_ports = raw1394_get_port_info( handle, pinf, 16 ) ) < 0 ) + { + fprintf( stderr, "raw1394 - failed to get port info: %s.\n", strerror( errno ) ); + raw1394_destroy_handle( handle ); + exit( EXIT_FAILURE ); + } +printf("n_ports: %d\n", n_ports); + /* tell raw1394 which host adapter to use */ + if ( raw1394_set_port( handle, port ) < 0 ) + { + fprintf( stderr, "raw1394 - failed to set set port: %s.\n", strerror( errno ) ); + exit( EXIT_FAILURE ); + } + + raw1394_set_iso_handler( handle, channel, raw_reader); // 63 is default channel... sucks. + raw1394_set_userdata( handle, ( void* ) NULL); + printf("fisk: %d\n", raw1394_start_iso_rcv( handle, channel)); fflush(stdout); + +/* if(fc == NULL) { errobj->pushError("Decoder not initialized."); return; } - +*/ while(*running) { AVPacket pkt; uint8_t *ptr; int len; SDL_Event user_event; - av_read_packet(fc, &pkt); - len = pkt.size; +// av_read_packet(fc, &pkt); + + while(1) + { + raw1394_loop_iterate(handle); +//printf("-"); fflush(stdout); + pkt.data = (uint8_t *)raw1394_get_userdata(handle); + if(pkt.data) + { + raw1394_set_userdata(handle, NULL); + break; + } + } +printf("."); fflush(stdout); + len = pkt.size = DVPACKAGE_SIZE; ptr = pkt.data; + pkt.stream_index = 0; // NOTE: we only decode video, we only need the data from stream_index 0 // (stream 0: video, stream 1: audio) @@ -119,15 +242,15 @@ void Decoder::decode() int ret; int got_picture; // buf_t *buf = buf_alloc(); - FFFrame *fff = new FFFrame(); - DVFrame *dvf = new DVFrame(); - dvf->type = DVF_VIDEO; + FFFrame *fff = new FFFrame(); ALLOC(fff, "FFFrame in decode"); +// DVFrame *dvf = new DVFrame(); ALLOC(dvf, "DVFrame in decode"); +// dvf->type = DVF_VIDEO; - memcpy(dvf->frame, ptr, len); +// memcpy(dvf->frame, ptr, len); //printf("DVBufferSize: [%d]bytes\n", len); - ret = avcodec_decode_video(&fc->streams[0]->codec, + ret = avcodec_decode_video(&mycodec/*&fc->streams[0]->codec*/, fff->frame, &got_picture, ptr, len); if(ret < 0) { @@ -139,7 +262,7 @@ void Decoder::decode() ptr += ret; pthread_mutex_lock(mutex); - encode_queue->push(dvf); +// encode_queue->push(dvf); player_queue->push(fff); pthread_mutex_unlock(mutex); @@ -149,8 +272,9 @@ void Decoder::decode() user_event.user.code = 0; user_event.user.data1 = NULL; user_event.user.data2 = NULL; - SDL_PushEvent(&user_event); +// SDL_PushEvent(&user_event); } +free(ptr); /* // For later use, when audio must be implemented while(pkt.stream_index == 1 && len > 0) { @@ -169,7 +293,7 @@ void Decoder::decode() sem_post(encode_sem); } */ - av_free_packet(&pkt); +// av_free_packet(&pkt); FREE(&pkt); } /* Kick the others so they wake up with empty queues */ diff --git a/src/dvframe.cc b/src/dvframe.cc index 229332c..c1948ba 100644 --- a/src/dvframe.cc +++ b/src/dvframe.cc @@ -30,12 +30,10 @@ DVFrame::DVFrame() { - // frame = avcodec_alloc_frame(); memset(frame, 0, sizeof(frame)); } DVFrame::~DVFrame() { - // av_free(frame); } diff --git a/src/ffframe.cc b/src/ffframe.cc index cdce5ae..b6d8e14 100644 --- a/src/ffframe.cc +++ b/src/ffframe.cc @@ -26,13 +26,15 @@ #include #include "ffframe.h" +#include "debug.h" + FFFrame::FFFrame() { - frame = avcodec_alloc_frame(); + frame = avcodec_alloc_frame(); ALLOC(frame, "FFFrame (inside obj)"); } FFFrame::~FFFrame() { - av_free(frame); + av_free(frame); FREE(frame); } diff --git a/src/img_encoder.cc b/src/img_encoder.cc index 75801c8..1a464f8 100644 --- a/src/img_encoder.cc +++ b/src/img_encoder.cc @@ -25,6 +25,8 @@ #include //#include +#include "debug.h" + //av_alloc_format_context //av_destruct_packet_nofree @@ -43,7 +45,7 @@ ImgEncoder::ImgEncoder() exit(1); } - dcc= avcodec_alloc_context(); + dcc= avcodec_alloc_context(); ALLOC(dcc, "img_encoder, dcc"); // open it if (avcodec_open(dcc, deccodec) < 0) { @@ -62,7 +64,7 @@ void ImgEncoder::encode(DVFrame *dvframe, int quality) { int ret; - AVFrame *rawframe = avcodec_alloc_frame(); + AVFrame *rawframe = avcodec_alloc_frame(); ALLOC(dcc, "img_encoder, rawframe"); ///////////////////////// DECODE uint8_t *ptr; @@ -81,7 +83,7 @@ void ImgEncoder::encode(DVFrame *dvframe, // TODO: Do image convertion here! AVPicture pict; - avpicture_alloc(&pict,PIX_FMT_RGB24, 720, 576); + avpicture_alloc(&pict,PIX_FMT_RGB24, 720, 576); ALLOC(dcc, "img_encoder, pict"); img_convert(&pict, PIX_FMT_RGB24, (AVPicture *)rawframe, PIX_FMT_YUV420P, 720, 576); @@ -89,8 +91,8 @@ void ImgEncoder::encode(DVFrame *dvframe, writeJPEGFile(filename, quality, (JSAMPLE*)(pict.data[0]), 720, 576); printf("written\n"); - avpicture_free(&pict); - av_free(rawframe); + avpicture_free(&pict); FREE(&pict); + av_free(rawframe); FREE(rawframe); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/miav.cc b/src/miav.cc index 4d53bc5..cfd8770 100644 --- a/src/miav.cc +++ b/src/miav.cc @@ -97,6 +97,8 @@ int server(int argc, char *argv[]) { return 0; } +#include "debug.h" + int main(int argc, char *argv[]) { int mode = MODE_GRAB; diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc index 92b2657..ece1cff 100644 --- a/src/mov_encoder.cc +++ b/src/mov_encoder.cc @@ -23,6 +23,7 @@ #include "mov_encoder.h" +#include "debug.h" //av_alloc_format_context //av_destruct_packet_nofree @@ -38,7 +39,8 @@ MovEncoder::MovEncoder(const char *filename) if(!(efc = av_alloc_format_context())) { fprintf(stderr, "Could not alloc output format context\n"); exit(1); - } + } + ALLOC(dcc, "mov_encoder, efc"); efc->oformat = guess_format("mpeg", NULL, NULL); //efc->oformat = guess_format(NULL, filename, NULL); @@ -129,7 +131,7 @@ MovEncoder::MovEncoder(const char *filename) exit(1); } - video_buffer = (unsigned char *)av_malloc(VIDEO_BUFFER_SIZE); + video_buffer = (unsigned char *)av_malloc(VIDEO_BUFFER_SIZE); ALLOC(dcc, "mov_encoder, video_buffer"); av_init_packet(&epkt); @@ -149,7 +151,7 @@ MovEncoder::MovEncoder(const char *filename) exit(1); } - dcc= avcodec_alloc_context(); + dcc= avcodec_alloc_context(); ALLOC(dcc, "mov_encoder, dcc"); /* open it */ if (avcodec_open(dcc, deccodec) < 0) { @@ -160,14 +162,14 @@ MovEncoder::MovEncoder(const char *filename) MovEncoder::~MovEncoder() { - av_free(video_buffer); + av_free(video_buffer); FREE(video_buffer); url_fclose(&efc->pb); } void MovEncoder::encode(DVFrame *dvframe) { int ret; - AVFrame *rawframe = avcodec_alloc_frame(); + AVFrame *rawframe = avcodec_alloc_frame();ALLOC(dcc, "mov_encoder, rawframe"); ///////////////////////// DECODE uint8_t *ptr; @@ -203,5 +205,5 @@ void MovEncoder::encode(DVFrame *dvframe) av_write_frame(efc, &epkt); - av_free(rawframe); + av_free(rawframe); FREE(rawframe); } -- cgit v1.2.3