void * loop_out(void * arg) { loop_handle * hd = (loop_handle *) arg; sv_fifo_bufferinfo infodst; sv_fifo_info status_dst; int lastdrop_dst = 0; int displaytick = 0; int res = SV_OK; int bufferid; int fifo_running = FALSE; int flip = 0; dvs_cond_wait(&hd->common.ready, &hd->common.lock, FALSE); while (hd->running) { // check for sync is detected and if genlocked when sync is on the refin while((res == SV_ERROR_SYNC_MISSING) || sv_fifo_sanitycheck(hd->svdst, hd->fifodst) == SV_ERROR_SYNC_MISSING && hd->running) { if(fifo_running) { fifo_running = FALSE; printf("WARNING: lost genlock! Output fifo stopped.\n"); res = sv_fifo_stop(hd->svdst, hd->fifodst, SV_FIFO_FLAG_FLUSH); if(res != SV_OK) { printf("sv_fifo_stop(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } res = sv_fifo_reset(hd->svdst, hd->fifodst); if(res != SV_OK) { printf("sv_fifo_reset(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } } sv_fifo_vsyncwait(hd->svdst, hd->fifodst); } if(!fifo_running) { printf("====> Restarting output fifo. <=====\n"); #if 0 res = sv_fifo_free(hd->svdst, hd->fifodst); if(res != SV_OK) { printf("sv_fifo_reset(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } // Init output FIFO. res = sv_fifo_init(hd->svdst, &hd->fifodst, FALSE, FALSE, TRUE, (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0), 0 ); if(res != SV_OK) { printf("sv_fifo_init(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; return; } res = sv_fifo_sanitylevel(hd->svdst, hd->fifodst, SV_FIFO_SANITY_LEVEL_FATAL, SV_FIFO_SANITY_VERSION_1); if(res != SV_OK) { printf("sv_fifo_sanitylevel(dst) failed %d '%s'\n", res, sv_geterrortext(res)); } #endif res = sv_fifo_startex(hd->svdst, hd->fifodst, &displaytick, NULL, NULL, NULL); if(res != SV_OK) { printf("sv_fifo_start(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } fifo_running = TRUE; } res = sv_fifo_getbuffer(hd->svdst, hd->fifodst, &hd->bufdst, NULL, SV_FIFO_FLAG_NODMAADDR | (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0) | (hd->bvideoonly ? SV_FIFO_FLAG_VIDEOONLY : 0) | (hd->baudioonly ? SV_FIFO_FLAG_AUDIOONLY : 0) | (hd->bfieldbased ? SV_FIFO_FLAG_FIELD : 0) | // enable field-based mode (hd->bvideoonly ? 0 : SV_FIFO_FLAG_SETAUDIOSIZE) | (hd->bottom2top ? SV_FIFO_FLAG_STORAGEMODE : 0) ); switch(res) { case SV_ERROR_SYNC_MISSING: continue; break; default: if(res != SV_OK) { printf("sv_fifo_getbuffer(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } break; } if(hd->bottom2top) { hd->bufdst->storage.storagemode = hd->storage.videomode & (SV_MODE_COLOR_MASK|SV_MODE_NBIT_MASK|SV_MODE_STORAGE_FRAME|SV_MODE_STORAGE_BOTTOM2TOP); hd->bufdst->storage.xsize = hd->storage.storagexsize; hd->bufdst->storage.ysize = hd->storage.storageysize; if(flip) { hd->bufdst->storage.storagemode |= SV_MODE_STORAGE_BOTTOM2TOP; } else { hd->bufdst->storage.storagemode &= ~SV_MODE_STORAGE_BOTTOM2TOP; } flip = (displaytick / 100) & 1; } dvs_mutex_enter(&hd->common.lock); bufferid = get_bufferid(hd, displaytick, hd->ndelay ); dvs_mutex_leave(&hd->common.lock); fill_buffer(hd, FALSE, hd->bufdst, bufferid); if(hd->banc && (bufferid >= 0)) { //Get list anc_element_t * current_element = &hd->anclist[bufferid]; //Try to get anc packets while( current_element->valid ) { current_element->valid = 0; res = sv_fifo_anc( hd->svsrc, hd->fifodst, hd->bufdst, ¤t_element->ancbuffer ); if( res == SV_OK ) { //Log if( hd->bverbose ) { printf("Displayed anc_element. Buffer:%d, DID:0x%x, SDID:0x%x\n", bufferid, current_element->ancbuffer.did, current_element->ancbuffer.sdid ); } if( current_element->next ) { current_element = current_element->next; } } } } res = sv_fifo_putbuffer(hd->svdst, hd->fifodst, hd->bufdst, &infodst); if(res != SV_OK) { printf("sv_fifo_putbuffer(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; break; } // Calculate next output tick. displaytick = infodst.when + hd->vinterlace; res = sv_fifo_status(hd->svdst, hd->fifodst, &status_dst); if(res != SV_OK) { printf("sv_fifo_status(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; break; } // Save output delay hd->outdelay_info = infodst.when - status_dst.displaytick; if(!hd->bverbose) { printf("\rDmaloop: %s in-delay:%2d/%d ticks out-delay:%2d ticks ", (bufferid!=-1) ? "running" : "no buffer", hd->indelay_info, hd->inavail_info, hd->outdelay_info); } if(hd->bverbose || (status_dst.dropped > lastdrop_dst)) { printf("ID %2d - out %06d %d %d %d (%u)\n", bufferid, infodst.when, status_dst.nbuffers, status_dst.availbuffers, status_dst.dropped - lastdrop_dst, infodst.clock_low); } // Report dropped frames in output FIFO. if(status_dst.dropped > lastdrop_dst) { printf("output fifo dropped - delay might have changed\n"); } lastdrop_dst = status_dst.dropped; /* * Wait until I need a new buffer */ if(hd->bfieldbased || hd->bdualsdi) { while(hd->running && ((status_dst.nbuffers - status_dst.availbuffers) > 3/*Fields*/)) { // Wait for next vsync res = sv_fifo_vsyncwait(hd->svdst, hd->fifodst); if(res != SV_OK) { printf("sv_fifo_vsyncwait(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } // Check buffer count res = sv_fifo_status(hd->svdst, hd->fifodst, &status_dst); if(res != SV_OK) { printf("sv_fifo_status(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } } } else { while(hd->running && ((status_dst.nbuffers - status_dst.availbuffers) > 2 /*Frames*/)) { // Wait for next vsync res = sv_fifo_vsyncwait(hd->svdst, hd->fifodst); if(res != SV_OK) { printf("sv_fifo_vsyncwait(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } // Check buffer count res = sv_fifo_status(hd->svdst, hd->fifodst, &status_dst); if(res != SV_OK) { printf("sv_fifo_status(dst) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } } } } res = sv_fifo_stop(hd->svdst, hd->fifodst, SV_FIFO_FLAG_FLUSH); if(res != SV_OK) { printf("sv_fifo_stop(dst) failed %d '%s'\n", res, sv_geterrortext(res)); } hd->exitcode = TRUE; dvs_thread_exit(&hd->exitcode, &hd->finish); return NULL; }
// // read_picture() // // Read from disk, write to dvs card static int read_picture(int card, sv_handle *sv, sv_fifo *poutput) { sv_fifo_buffer *pbuffer; int res; char frame[element_size]; // Get sv memmory buffer if ((res = sv_fifo_getbuffer(sv, poutput, &pbuffer, NULL, 0)) != SV_OK) { return res; } // Increasing the size of dma.size does not get audio samples only 0x80's // // dma buffer is structured as follows // // video frame offset= 0 // audio ch. 0, 1 offset= pbuffer->audio[0].addr[0] // audio ch. 2, 3 offset= pbuffer->audio[0].addr[1] // pbuffer->dma.addr = (char *)frame; pbuffer->dma.size = element_size; // video + audio int audio_size = 1920*2*4; char *video_buf = frame; char *audio_buf = frame + video_size; // if requested display black frames at start if (black_frames > 0 && black_frames_displayed < black_frames) { int i; for (i = 0; i < video_size; i+= 4) { video_buf[i+0] = 0x80; video_buf[i+1] = 0x80; video_buf[i+2] = 0x80; video_buf[i+3] = 0x80; } memcpy(video_buf, black_frame_buf, video_size); memset(audio_buf, 0, audio_size); memset(audio_buf + 0x4000, 0, audio_size); black_frames_displayed++; } else { int input_exhausted; READ_FROM_FILE: input_exhausted = 0; if ( fread(video_buf, video_size, 1, fp_video) != 1 ) { if (feof(fp_video)) input_exhausted = 1; else perror("fread from video file"); } current_video_frame++; if (no_audio) { memset(audio_buf, 0, audio_size); memset(audio_buf + 0x4000, 0, audio_size); } else { if ( fread(audio_buf, audio_size, 1, fp_audio12) != 1 ) { if (feof(fp_audio12)) input_exhausted = 1; else perror("fread from audio 12 file"); } if ( fread(audio_buf + 0x4000, audio_size, 1, fp_audio34) != 1 ) { if (feof(fp_audio34)) input_exhausted = 1; else perror("fread from audio 34 file"); } } if (input_exhausted) { if (loop) { printf("Reached end of input, looping\n"); fseeko(fp_video, frame_inpoint * video_size, SEEK_SET); current_video_frame = frame_inpoint; if (! no_audio) { fseeko(fp_audio12, frame_inpoint * audio_size, SEEK_SET); fseeko(fp_audio34, frame_inpoint * audio_size, SEEK_SET); } goto READ_FROM_FILE; } printf("Reached end of input\n"); exit(0); } if (frame_outpoint > 0 && current_video_frame >= frame_outpoint) { fseeko(fp_video, frame_inpoint * video_size, SEEK_SET); current_video_frame = frame_inpoint; if (! no_audio) { fseeko(fp_audio12, frame_inpoint * audio_size, SEEK_SET); fseeko(fp_audio34, frame_inpoint * audio_size, SEEK_SET); } } } // set timecode // doesn't appear to work i.e. get output over SDI int dvs_timecode = int_to_dvs_tc(timecode); pbuffer->timecode.vitc_tc = dvs_timecode; pbuffer->timecode.vitc_tc2 = dvs_timecode | 0x80000000; // set high bit for second field timecode // send the filled in buffer to the hardware SV_CHECK(sv_fifo_putbuffer(sv, poutput, pbuffer, NULL)); if (verbose > 1) { // timecode: // vitc_tc=268441105 vitc_tc2=-1879042543 for "10:00:16:11" printf("card %d: element_size=%d vitc_tc=%08x vitc_tc2=%8x tc_int=%d\n", card, element_size, pbuffer->timecode.vitc_tc, pbuffer->timecode.vitc_tc2, timecode); fflush(stdout); } timecode++; return SV_OK; }
void * loop_in(void * arg) { loop_handle * hd = (loop_handle *) arg; sv_fifo_bufferinfo infosrc; sv_fifo_info status_src; unsigned int lastdrop_src = (unsigned int) ~0; int bufferid; int res = SV_OK; /* // Start the input FIFO. */ res = sv_fifo_start(hd->svsrc, hd->fifosrc); if(res != SV_OK) { printf("sv_fifo_start(src) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } while (hd->running) { /* // >>> Handle input FIFO <<< */ do { res = sv_fifo_getbuffer(hd->svsrc, hd->fifosrc, &hd->bufsrc, NULL, SV_FIFO_FLAG_NODMAADDR | (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0) | (hd->bvideoonly ? SV_FIFO_FLAG_VIDEOONLY : 0) | (hd->baudioonly ? SV_FIFO_FLAG_AUDIOONLY : 0) | (hd->bplayback ? SV_FIFO_FLAG_FLUSH : 0) ); switch(res) { case SV_ERROR_NOCARRIER: case SV_ERROR_INPUT_VIDEO_NOSIGNAL: case SV_ERROR_INPUT_VIDEO_RASTER: case SV_ERROR_INPUT_VIDEO_DETECTING: case SV_ERROR_INPUT_KEY_NOSIGNAL: case SV_ERROR_INPUT_KEY_RASTER: printf("v"); // Inform user about missing video fflush(stdout); res = SV_ACTIVE; break; case SV_ERROR_INPUT_AUDIO_NOAIV: case SV_ERROR_INPUT_AUDIO_NOAESEBU: // In these two cases, getbuffer returned a valid buffer. // So, we can continue without audio. printf("a"); // Inform user about missing audio fflush(stdout); res = SV_OK; break; case SV_ERROR_VSYNCPASSED: printf("NOTE: vsyncpassed possibly caused by signal disconnect\n"); res = SV_ACTIVE; break; default:; } if(res == SV_ACTIVE) { // wait for next vsync and try again sv_fifo_vsyncwait(hd->svsrc, hd->fifosrc); } } while(res == SV_ACTIVE && hd->running); if (res != SV_OK) { printf("sv_fifo_getbuffer(src) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; break; } dvs_mutex_enter(&hd->common.lock); bufferid = get_free_bufferid(hd); dvs_mutex_leave(&hd->common.lock); fill_buffer(hd, TRUE, hd->bufsrc, bufferid); if(hd->banc && (bufferid >= 0)) { //Get list pointer anc_element_t * current_element = &hd->anclist[bufferid]; //If there are valid packets delete them if( current_element->next ) { //Delete all elements in list delete_element( bufferid, current_element->next ); //Set first element to zero memset( current_element, 0, sizeof(anc_element_t) ); } //Try to get anc packets while( res==SV_OK ) { res = sv_fifo_anc( hd->svsrc, hd->fifosrc, hd->bufsrc, ¤t_element->ancbuffer ); if( res == SV_OK ) { current_element->valid = 1; //Log if( hd->bverbose ) { printf("Recorded anc_element. Buffer:%d, DID:0x%x, SDID:0x%x\n", bufferid, current_element->ancbuffer.did, current_element->ancbuffer.sdid ); } //I need to allocate one more packet buffer current_element->next = malloc( sizeof( anc_element_t )); if( current_element->next != 0 ) { //Set all values to zero memset( current_element->next, 0, sizeof( anc_element_t )); //Build the list current_element->next->prev = current_element; current_element = current_element->next; } else { printf("malloc failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; } } } // This errorcode shows that no more packets are in the frame if( res == SV_ERROR_NOTAVAILABLE ) { res = SV_OK; } } res = sv_fifo_putbuffer(hd->svsrc, hd->fifosrc, hd->bufsrc, &infosrc); if(res != SV_OK) { printf("sv_fifo_putbuffer(src) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; break; } res = sv_fifo_status(hd->svsrc, hd->fifosrc, &status_src); if(res != SV_OK) { printf("sv_fifo_status(src) failed %d '%s'\n", res, sv_geterrortext(res)); hd->running = FALSE; break; } // Save input delay hd->indelay_info = status_src.recordtick - infosrc.when; hd->inavail_info = status_src.availbuffers; if(hd->bverbose || ((unsigned int)status_src.dropped > lastdrop_src)) { printf("ID %2d - in %06d %d %d %d (%u)\n", bufferid, infosrc.when, status_src.nbuffers, status_src.availbuffers, status_src.dropped - lastdrop_src, infosrc.clock_low); } // Report dropped frames in input FIFO. if((unsigned int)status_src.dropped > lastdrop_src) { printf("input fifo dropped - delay might have changed\n"); } lastdrop_src = status_src.dropped; dvs_mutex_enter(&hd->common.lock); if(bufferid >= 0) { hd->common.inputtick[bufferid] = infosrc.when; } dvs_mutex_leave(&hd->common.lock); /* // Signal that a new input buffer is ready */ dvs_cond_broadcast(&hd->common.ready, &hd->common.lock, FALSE); } res = sv_fifo_stop(hd->svsrc, hd->fifosrc, 0); if(res != SV_OK) { printf("sv_fifo_stop(src) failed %d '%s'\n", res, sv_geterrortext(res)); } hd->exitcode = TRUE; dvs_thread_exit(&hd->exitcode, &hd->finish); return NULL; }