/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * RTVideoRec Realtime video recoder and encoder for Linux * * Copyright (C) 2004 Bent Bisballe * Copyright (C) 2004 B. Stultiens * Copyright (C) 2004 Koen Otter and Glenn van der Meyden * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #ifdef USE_GUI #include #include #include #include #include #include "decoder.h" #include "debug.h" static AVCodecContext mycodec; Decoder::Decoder(Error* err, char *device, int channel, sem_t *gencode_sem, sem_t *gplayer_sem, Queue *gencode_queue, Queue *gplayer_queue, pthread_mutex_t *gmutex, volatile int *grunning) { errobj = err; device = ""; encode_sem = gencode_sem; player_sem = gplayer_sem; encode_queue = gencode_queue; player_queue = gplayer_queue; mutex = gmutex; running = grunning; AVFormatContext *ifc; AVFormatParameters dvpars; AVInputFormat *iformat; AVCodec *dec_codec; /* memset(&dvpars, 0, sizeof(dvpars)); if(!(iformat = av_find_input_format("dv1394"))) { errobj->pushError("Failed to get input format dv1394."); fc = NULL; return; } dvpars.device = device; // "/dev/dv1394"; dvpars.channel = channel; dvpars.standard = "pal"; 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; } if(av_find_stream_info(ifc) < 0) { errobj->pushError("Could not find enough parameters."); fc = NULL; // return; } dump_format(ifc, 1, "", 0); */ 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(&mycodec/*&ifc->streams[0]->codec*/, dec_codec) < 0) { errobj->pushError("Error while opening codec for input stream."); fc = NULL; return; } fc = ifc; } Decoder::~Decoder() { avcodec_close(&fc->streams[0]->codec); 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); 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) // while(pkt.stream_index == 0 && len > 0) { while(pkt.stream_index == 0 && len > 0) { int ret; int got_picture; // buf_t *buf = buf_alloc(); 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); //printf("DVBufferSize: [%d]bytes\n", len); ret = avcodec_decode_video(&mycodec/*&fc->streams[0]->codec*/, fff->frame, &got_picture, ptr, len); if(ret < 0) { errobj->pushError("Error while decoding stream."); return; } len -= ret; ptr += ret; pthread_mutex_lock(mutex); // encode_queue->push(dvf); player_queue->push(fff); pthread_mutex_unlock(mutex); sem_post(encode_sem); user_event.type = SDL_USEREVENT; user_event.user.code = 0; user_event.user.data1 = NULL; user_event.user.data2 = NULL; // SDL_PushEvent(&user_event); } free(ptr); /* // For later use, when audio must be implemented while(pkt.stream_index == 1 && len > 0) { DVFrame *dvf = new DVFrame(); dvf->type = DVF_AUDIO; memcpy(dvf->frame, ptr, sizeof(dvf->frame)); ptr += sizeof(dvf->frame); len -= sizeof(dvf->frame); pthread_mutex_lock(mutex); encode_queue->push(dvf); pthread_mutex_unlock(mutex); sem_post(encode_sem); } */ // av_free_packet(&pkt); FREE(&pkt); } /* Kick the others so they wake up with empty queues */ sem_post(encode_sem); pthread_exit(NULL); } void Decoder::run() { decode(); } #endif /*USE_GUI*/