/* -*- 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 #include "decoder.h" Decoder::Decoder(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) { 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"))) { fprintf(stderr, "Failed to get input format dv1394\n"); exit(1); } dvpars.device = device; /* "/dev/dv1394"; */ dvpars.channel = channel; dvpars.standard = "pal"; if(av_open_input_file(&ifc, "", iformat, 0, &dvpars) < 0) { fprintf(stderr, "Device is in use\n"); fc = NULL; return; } if(av_find_stream_info(ifc) < 0) { fprintf (stderr, "Could not find enough parameters\n"); fc = NULL; return; } dump_format(ifc, 1, "", 0); if(!(dec_codec = avcodec_find_decoder(ifc->streams[0]->codec.codec_id))) { printf("Unsupported codec for input stream \n"); fc = NULL; return; } if(avcodec_open(&ifc->streams[0]->codec, dec_codec) < 0) { printf("Error while opening codec for input stream\n"); fc = NULL; return; } fc = ifc; } Decoder::~Decoder() { avcodec_close(&fc->streams[0]->codec); av_close_input_file(fc); } void Decoder::decode() { if(fc == NULL) { printf("Decoder not initialized.\n"); return; } while(*running) { AVPacket pkt; uint8_t *ptr; int len; SDL_Event user_event; av_read_packet(fc, &pkt); len = pkt.size; ptr = pkt.data; /* 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) { int ret; int got_picture; // buf_t *buf = buf_alloc(); FFFrame *fff = new FFFrame(); DVFrame *dvf = new DVFrame(); dvf->type = DVF_VIDEO; memcpy(dvf->frame, ptr, len); // fprintf(stderr, "DVBufferSize: [%d]bytes\n", len); ret = avcodec_decode_video(&fc->streams[0]->codec, fff->frame, &got_picture, ptr, len); if(ret < 0) { fprintf(stderr, "Error while decoding stream\n"); exit(1); } 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); } /* // 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); } /* Kick the others so they wake up with empty queues */ sem_post(encode_sem); pthread_exit(NULL); } void Decoder::run() { decode(); }