/***************************************************************************** * NewUDPPacket: allocate a new UDP packet of size p_sys->i_mtu *****************************************************************************/ static block_t *NewUDPPacket( sout_access_out_t *p_access, mtime_t i_dts) { sout_access_out_sys_t *p_sys = p_access->p_sys; block_t *p_buffer; while ( block_FifoCount( p_sys->p_empty_blocks ) > MAX_EMPTY_BLOCKS ) { p_buffer = block_FifoGet( p_sys->p_empty_blocks ); block_Release( p_buffer ); } if( block_FifoCount( p_sys->p_empty_blocks ) == 0 ) { p_buffer = block_Alloc( p_sys->i_mtu ); } else { p_buffer = block_FifoGet(p_sys->p_empty_blocks ); p_buffer->i_flags = 0; p_buffer = block_Realloc( p_buffer, 0, p_sys->i_mtu ); } p_buffer->i_dts = i_dts; p_buffer->i_buffer = 0; return p_buffer; }
static int MuxBlock( sout_mux_t *p_mux, sout_input_t *p_input ) { sout_mux_sys_t *p_sys = p_mux->p_sys; block_t *p_data = block_FifoGet( p_input->p_fifo ); int i_stream = *((int *)p_input->p_sys); AVStream *p_stream = p_sys->oc->streams[i_stream]; AVPacket pkt; memset( &pkt, 0, sizeof(AVPacket) ); av_init_packet(&pkt); pkt.data = p_data->p_buffer; pkt.size = p_data->i_buffer; pkt.stream_index = i_stream; if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) { #ifdef AVFMT_ALLOW_FLUSH /* Make sure we don't inadvertedly mark buffered data as keyframes. */ if( p_sys->oc->oformat->flags & AVFMT_ALLOW_FLUSH ) av_write_frame( p_sys->oc, NULL ); #endif p_sys->b_write_keyframe = true; pkt.flags |= AV_PKT_FLAG_KEY; } if( p_data->i_pts > 0 ) pkt.pts = p_data->i_pts * p_stream->time_base.den / CLOCK_FREQ / p_stream->time_base.num; if( p_data->i_dts > 0 ) pkt.dts = p_data->i_dts * p_stream->time_base.den / CLOCK_FREQ / p_stream->time_base.num; /* this is another hack to prevent libavformat from triggering the "non monotone timestamps" check in avformat/utils.c */ p_stream->cur_dts = ( p_data->i_dts * p_stream->time_base.den / CLOCK_FREQ / p_stream->time_base.num ) - 1; if( av_write_frame( p_sys->oc, &pkt ) < 0 ) { msg_Err( p_mux, "could not write frame (pts: %"PRId64", dts: %"PRId64") " "(pkt pts: %"PRId64", dts: %"PRId64")", p_data->i_pts, p_data->i_dts, pkt.pts, pkt.dts ); block_Release( p_data ); return VLC_EGENERIC; } block_Release( p_data ); return VLC_SUCCESS; }
void *fifo_getTask(void *argc) { block_t *p_block; int sleep_flag; ThreadAlive[PTASK1] = TRUE; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_cleanup_push(ThreadCleanUp, (void *)NULL); sleep_flag = 0; for (;;) { if (ThreadAlive[PTASK1] != TRUE) { break; } /* Check DB handler1, 10s */ sleep_flag++; if (sleep_flag > 50000) { #if 0 CheckTimeHLR1(); #endif sleep_flag = 0; } if ((p_block = block_FifoGet(TcpFifo)) == NULL) { continue; } FifoGet_Event(p_block); block_Release(p_block); } ThreadAlive[PTASK1] = FALSE; ThreadFlags[PTASK1] = FALSE; pthread_cleanup_pop(1); return(NULL); }
static void* CommandThread( void *obj ) { vod_t *p_vod = (vod_t*)obj; vod_sys_t *p_sys = p_vod->p_sys; for( ;; ) { block_t *p_block_cmd = block_FifoGet( p_sys->p_fifo_cmd ); rtsp_cmd_t cmd; if( !p_block_cmd ) break; int canc = vlc_savecancel (); memcpy( &cmd, p_block_cmd->p_buffer, sizeof(cmd) ); block_Release( p_block_cmd ); /* */ switch( cmd.i_type ) { case RTSP_CMD_TYPE_ADD: MediaSetup(p_vod, cmd.p_media, cmd.psz_arg); break; case RTSP_CMD_TYPE_DEL: MediaDel(p_vod, cmd.p_media); break; case RTSP_CMD_TYPE_STOP: vod_MediaControl( p_vod, cmd.p_media, cmd.psz_arg, VOD_MEDIA_STOP ); break; default: break; } free( cmd.psz_arg ); vlc_restorecancel (canc); } return NULL; }
static ssize_t DStreamRead( stream_t *s, void *buf, size_t len ) { stream_sys_t *sys = s->p_sys; if( !atomic_load( &sys->active ) ) return -1; if( s->b_error ) return -1; if( len == 0 ) return 0; //msg_Dbg( s, "DStreamRead: wanted %d bytes", i_read ); block_t *block = sys->p_block; if( block == NULL ) { block = block_FifoGet( sys->p_fifo ); if( block == NULL ) { s->b_error = true; return -1; } sys->p_block = block; } size_t copy = __MIN( len, block->i_buffer ); if( buf != NULL && copy > 0 ) memcpy( buf, block->p_buffer, copy ); block->p_buffer += copy; block->i_buffer -= copy; if( block->i_buffer == 0 ) { block_Release( block ); sys->p_block = NULL; } sys->i_pos += copy; return copy; }
/***************************************************************************** * Close: *****************************************************************************/ void CloseVoD( vlc_object_t * p_this ) { vod_t *p_vod = (vod_t *)p_this; vod_sys_t *p_sys = p_vod->p_sys; /* Stop command thread */ vlc_cancel( p_sys->thread ); vlc_join( p_sys->thread, NULL ); while( block_FifoCount( p_sys->p_fifo_cmd ) > 0 ) { rtsp_cmd_t cmd; block_t *p_block_cmd = block_FifoGet( p_sys->p_fifo_cmd ); memcpy( &cmd, p_block_cmd->p_buffer, sizeof(cmd) ); block_Release( p_block_cmd ); if ( cmd.i_type == RTSP_CMD_TYPE_DEL ) MediaDel(p_vod, cmd.p_media); free( cmd.psz_arg ); } block_FifoRelease( p_sys->p_fifo_cmd ); free( p_sys->psz_rtsp_path ); free( p_sys ); }
/**************************************************************************** * Encode: the whole thing **************************************************************************** * This function spits out encapsulation units. ****************************************************************************/ static block_t *Encode( encoder_t *p_enc, picture_t *p_pic ) { encoder_sys_t *p_sys = p_enc->p_sys; block_t *p_block, *p_output_chain = NULL; int i_plane, i_line, i_width, i_src_stride; uint8_t *p_dst; if( !p_pic ) return NULL; /* we only know if the sequence is interlaced when the first * picture arrives, so final setup is done here */ /* XXX todo, detect change of interlace */ p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first; p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive; if( p_sys->b_auto_field_coding ) p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive; if( !p_sys->p_dirac ) { date_t date; /* Initialise the encoder with the encoder context */ p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 ); if( !p_sys->p_dirac ) { msg_Err( p_enc, "Failed to initialize dirac encoder" ); return NULL; } date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base ); #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2) int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac ); i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1; date_Increment( &date, i_delayinpics ); #else date_Increment( &date, 1 ); #endif p_sys->i_pts_offset = date_Get( &date ); /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced * for each frame input. Calculate time between fields for offsetting * the second field later. */ if( 1 == p_sys->ctx.enc_params.picture_coding_mode ) { date_Set( &date, 0 ); date_Increment( &date, 1 ); p_sys->i_field_time = date_Get( &date ) / 2; } } /* Copy input picture into encoder input buffer (stride by stride) */ /* Would be lovely to just pass the picture in, but there is noway for the * library to free it */ p_dst = p_sys->p_buffer_in; for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { uint8_t *p_src = p_pic->p[i_plane].p_pixels; i_width = p_pic->p[i_plane].i_visible_pitch; i_src_stride = p_pic->p[i_plane].i_pitch; for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ ) { vlc_memcpy( p_dst, p_src, i_width ); p_dst += i_width; p_src += i_src_stride; } } /* Load one frame of data into encoder */ if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in, p_sys->i_buffer_in ) < 0 ) { msg_Dbg( p_enc, "dirac_encoder_load() error" ); return NULL; } /* store pts in a lookaside buffer, so that the same pts may * be used for the picture in coded order */ StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date ); p_sys->i_input_picnum++; /* store dts in a queue, so that they appear in order in * coded order */ p_block = block_New( p_enc, 1 ); if( !p_block ) return NULL; p_block->i_dts = p_pic->date - p_sys->i_pts_offset; block_FifoPut( p_sys->p_dts_fifo, p_block ); p_block = NULL; /* for field coding mode, insert an extra value into both the * pts lookaside buffer and dts queue, offset to correspond * to a one field delay. */ if( 1 == p_sys->ctx.enc_params.picture_coding_mode ) { StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time ); p_sys->i_input_picnum++; p_block = block_New( p_enc, 1 ); if( !p_block ) return NULL; p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time; block_FifoPut( p_sys->p_dts_fifo, p_block ); p_block = NULL; } dirac_encoder_state_t state; /* Retrieve encoded frames from encoder */ do { p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out; p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out; state = dirac_encoder_output( p_sys->p_dirac ); switch( state ) { case ENC_STATE_AVAIL: { uint32_t pic_num; /* extract data from encoder temporary buffer. */ p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size ); if( !p_block ) return NULL; memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer, p_sys->p_dirac->enc_buf.size ); /* if some flags were set for a previous block, prevent * them from getting lost */ if( p_sys->p_chain ) p_block->i_flags |= p_sys->p_chain->i_flags; /* store all extracted blocks in a chain and gather up when an * entire encapsulation unit is avaliable (ends with a picture) */ block_ChainAppend( &p_sys->p_chain, p_block ); /* Presence of a Sequence header indicates a seek point */ if( 0 == p_block->p_buffer[4] ) { p_block->i_flags |= BLOCK_FLAG_TYPE_I; if( !p_enc->fmt_out.p_extra ) { const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 }; uint32_t len = GetDWBE( p_block->p_buffer + 5 ); /* if it hasn't been done so far, stash a copy of the * sequence header for muxers such as ogg */ /* The OggDirac spec advises that a Dirac EOS DataUnit * is appended to the sequence header to allow guard * against poor streaming servers */ /* XXX, should this be done using the packetizer ? */ p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) ); if( !p_enc->fmt_out.p_extra ) return NULL; memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len); memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) ); SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len ); p_enc->fmt_out.i_extra = len + sizeof(eos); } } if( ReadDiracPictureNumber( &pic_num, p_block ) ) { /* Finding a picture terminates an ecapsulation unit, gather * all data and output; use the next dts value queued up * and find correct pts in the tlb */ p_block = block_FifoGet( p_sys->p_dts_fifo ); p_sys->p_chain->i_dts = p_block->i_dts; p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num ); block_Release( p_block ); block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) ); p_sys->p_chain = NULL; } else { p_block = NULL; } break; } case ENC_STATE_BUFFER: break; case ENC_STATE_INVALID: default: break; } } while( state == ENC_STATE_AVAIL ); return p_output_chain; }
/* We split/pack PCM blocks to a fixed size: pcm_chunk_size bytes */ static block_t *GetPCM( encoder_t *p_enc, aout_buffer_t *p_block ) { encoder_sys_t *p_sys = p_enc->p_sys; block_t *p_pcm_block; if( !p_block ) goto buffered; /* just return a block if we can */ /* Put the PCM samples sent by VLC in the Fifo */ while( p_sys->i_buffer + p_block->i_buffer >= pcm_chunk_size ) { unsigned int i_buffer = 0; p_pcm_block = block_New( p_enc, pcm_chunk_size ); if( !p_pcm_block ) break; if( p_sys->i_buffer ) { vlc_memcpy( p_pcm_block->p_buffer, p_sys->p_buffer, p_sys->i_buffer ); i_buffer = p_sys->i_buffer; p_sys->i_buffer = 0; free( p_sys->p_buffer ); } vlc_memcpy( p_pcm_block->p_buffer + i_buffer, p_block->p_buffer, pcm_chunk_size - i_buffer ); p_block->p_buffer += pcm_chunk_size - i_buffer; p_block->i_buffer -= pcm_chunk_size - i_buffer; block_FifoPut( p_sys->p_fifo, p_pcm_block ); } /* We hadn't enough data to make a block, put it in standby */ if( p_block->i_buffer ) { uint8_t *p_tmp; if( p_sys->i_buffer > 0 ) p_tmp = realloc( p_sys->p_buffer, p_block->i_buffer + p_sys->i_buffer ); else p_tmp = malloc( p_block->i_buffer ); if( !p_tmp ) { p_sys->i_buffer = 0; free( p_sys->p_buffer ); p_sys->p_buffer = NULL; return NULL; } p_sys->p_buffer = p_tmp; vlc_memcpy( p_sys->p_buffer + p_sys->i_buffer, p_block->p_buffer, p_block->i_buffer ); p_sys->i_buffer += p_block->i_buffer; p_block->i_buffer = 0; } buffered: /* and finally get a block back */ return block_FifoCount( p_sys->p_fifo ) > 0 ? block_FifoGet( p_sys->p_fifo ) : NULL; }
/** * Update thread which do the rendering * @param p_this: the p_thread object */ static void *Thread( void *p_data ) { filter_t *p_filter = (filter_t*)p_data; filter_sys_t *p_sys = p_filter->p_sys; video_format_t fmt; vlc_gl_t *gl; unsigned int i_last_width = 0; unsigned int i_last_height = 0; /* Create the openGL provider */ p_sys->p_vout = (vout_thread_t *)vlc_object_create(p_filter, sizeof(vout_thread_t)); if (!p_sys->p_vout) goto error; /* Configure the video format for the opengl provider. */ video_format_Init(&fmt, 0); video_format_Setup(&fmt, VLC_CODEC_RGB32, p_sys->i_width, p_sys->i_height, 0, 1 ); fmt.i_sar_num = 1; fmt.i_sar_den = 1; /* Init vout state. */ vout_display_state_t state; memset(&state, 0, sizeof(state)); state.cfg.display.sar.num = 1; state.cfg.display.sar.den = 1; state.cfg.is_display_filled = true; state.cfg.zoom.num = 1; state.cfg.zoom.den = 1; state.sar.num = 1; state.sar.den = 1; p_sys->p_vd = vout_NewDisplay(p_sys->p_vout, &fmt, &state, "opengl", 1000000, 1000000); if (!p_sys->p_vd) { vlc_object_release(p_sys->p_vout); goto error; } gl = vout_GetDisplayOpengl(p_sys->p_vd); if (!gl) { vout_DeleteDisplay(p_sys->p_vd, NULL); vlc_object_release(p_sys->p_vout); goto error; } vlc_sem_post(&p_sys->ready); initOpenGLScene(); float height[NB_BANDS] = {0}; while (1) { block_t *block = block_FifoGet(p_sys->fifo); int canc = vlc_savecancel(); /* Manage the events */ vout_ManageDisplay(p_sys->p_vd, true); if (p_sys->p_vd->cfg->display.width != i_last_width || p_sys->p_vd->cfg->display.height != i_last_height) { /* FIXME it is not perfect as we will have black bands */ vout_display_place_t place; vout_display_PlacePicture(&place, &p_sys->p_vd->source, p_sys->p_vd->cfg, false); i_last_width = p_sys->p_vd->cfg->display.width; i_last_height = p_sys->p_vd->cfg->display.height; } /* Horizontal scale for 20-band equalizer */ const unsigned xscale[] = {0,1,2,3,4,5,6,7,8,11,15,20,27, 36,47,62,82,107,141,184,255}; fft_state *p_state; /* internal FFT data */ unsigned i, j; float p_output[FFT_BUFFER_SIZE]; /* Raw FFT Result */ int16_t p_buffer1[FFT_BUFFER_SIZE]; /* Buffer on which we perform the FFT (first channel) */ int16_t p_dest[FFT_BUFFER_SIZE]; /* Adapted FFT result */ float *p_buffl = (float*)block->p_buffer; /* Original buffer */ int16_t *p_buffs; /* int16_t converted buffer */ int16_t *p_s16_buff; /* int16_t converted buffer */ /* Allocate the buffer only if the number of samples change */ if (block->i_nb_samples != p_sys->i_prev_nb_samples) { free(p_sys->p_prev_s16_buff); p_sys->p_prev_s16_buff = malloc(block->i_nb_samples * p_sys->i_channels * sizeof(int16_t)); if (!p_sys->p_prev_s16_buff) goto release; p_sys->i_prev_nb_samples = block->i_nb_samples; } p_buffs = p_s16_buff = p_sys->p_prev_s16_buff; /* Convert the buffer to int16_t Pasted from float32tos16.c */ for (i = block->i_nb_samples * p_sys->i_channels; i--;) { union {float f; int32_t i;} u; u.f = *p_buffl + 384.0; if (u.i > 0x43c07fff) *p_buffs = 32767; else if (u.i < 0x43bf8000) *p_buffs = -32768; else *p_buffs = u.i - 0x43c00000; p_buffl++; p_buffs++; } p_state = visual_fft_init(); if (!p_state) { msg_Err(p_filter,"unable to initialize FFT transform"); goto release; } p_buffs = p_s16_buff; for (i = 0 ; i < FFT_BUFFER_SIZE; i++) { p_output[i] = 0; p_buffer1[i] = *p_buffs; p_buffs += p_sys->i_channels; if (p_buffs >= &p_s16_buff[block->i_nb_samples * p_sys->i_channels]) p_buffs = p_s16_buff; } fft_perform (p_buffer1, p_output, p_state); for (i = 0; i< FFT_BUFFER_SIZE; ++i) p_dest[i] = p_output[i] * (2 ^ 16) / ((FFT_BUFFER_SIZE / 2 * 32768) ^ 2); for (i = 0 ; i < NB_BANDS; i++) { /* Decrease the previous size of the bar. */ height[i] -= BAR_DECREMENT; if (height[i] < 0) height[i] = 0; int y = 0; /* We search the maximum on one scale to determine the current size of the bar. */ for (j = xscale[i]; j < xscale[i + 1]; j++) { if (p_dest[j] > y) y = p_dest[j]; } /* Calculate the height of the bar */ float new_height = y != 0 ? log(y) * 0.4 : 0; height[i] = new_height > height[i] ? new_height : height[i]; } /* Determine the camera rotation angle. */ p_sys->f_rotationAngle += p_sys->f_rotationIncrement; if (p_sys->f_rotationAngle <= -ROTATION_MAX) p_sys->f_rotationIncrement = ROTATION_INCREMENT; else if (p_sys->f_rotationAngle >= ROTATION_MAX) p_sys->f_rotationIncrement = -ROTATION_INCREMENT; /* Render the frame. */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(p_sys->f_rotationAngle, 0, 1, 0); drawBars(height); glPopMatrix(); /* Wait to swapp the frame on time. */ mwait(block->i_pts + (block->i_length / 2)); if (!vlc_gl_Lock(gl)) { vlc_gl_Swap(gl); vlc_gl_Unlock(gl); } release: block_Release(block); vlc_restorecancel(canc); } assert(0); error: p_sys->b_error = true; vlc_sem_post(&p_sys->ready); return NULL; }
/***************************************************************************** * ThreadWrite: Write a packet on the network at the good time. *****************************************************************************/ static void* ThreadWrite( void *data ) { sout_access_out_t *p_access = data; sout_access_out_sys_t *p_sys = p_access->p_sys; mtime_t i_date_last = -1; const unsigned i_group = var_GetInteger( p_access, SOUT_CFG_PREFIX "group" ); mtime_t i_to_send = i_group; unsigned i_dropped_packets = 0; for (;;) { block_t *p_pk = block_FifoGet( p_sys->p_fifo ); mtime_t i_date, i_sent; i_date = p_sys->i_caching + p_pk->i_dts; if( i_date_last > 0 ) { if( i_date - i_date_last > 2000000 ) { if( !i_dropped_packets ) msg_Dbg( p_access, "mmh, hole (%"PRId64" > 2s) -> drop", i_date - i_date_last ); block_FifoPut( p_sys->p_empty_blocks, p_pk ); i_date_last = i_date; i_dropped_packets++; continue; } else if( i_date - i_date_last < -1000 ) { if( !i_dropped_packets ) msg_Dbg( p_access, "mmh, packets in the past (%"PRId64")", i_date_last - i_date ); } } block_cleanup_push( p_pk ); i_to_send--; if( !i_to_send || (p_pk->i_flags & BLOCK_FLAG_CLOCK) ) { mwait( i_date ); i_to_send = i_group; } if ( send( p_sys->i_handle, p_pk->p_buffer, p_pk->i_buffer, 0 ) == -1 ) msg_Warn( p_access, "send error: %s", vlc_strerror_c(errno) ); vlc_cleanup_pop(); if( i_dropped_packets ) { msg_Dbg( p_access, "dropped %i packets", i_dropped_packets ); i_dropped_packets = 0; } #if 1 i_sent = mdate(); if ( i_sent > i_date + 20000 ) { msg_Dbg( p_access, "packet has been sent too late (%"PRId64 ")", i_sent - i_date ); } #endif block_FifoPut( p_sys->p_empty_blocks, p_pk ); i_date_last = i_date; } return NULL; }