示例#1
0
VideoEncoder::~VideoEncoder() {
    // flush all the ringbuffer to file and stream
    unsigned int encnum = 0;

    if(encbuf) {
        do {
            if((encnum = ringbuffer_read_space(ringbuffer)) > 0)
                encnum = ringbuffer_read(ringbuffer, encbuf, encnum);
//                           ((audio_kbps + video_kbps)*1024)/24);

            if(encnum <= 0) break;

            if(write_to_disk && filedump_fd) {
                fwrite(encbuf, 1, encnum, filedump_fd);
            }

            if(write_to_stream && ice) {
                shout_sync(ice);
                shout_send(ice, (const unsigned char*)encbuf, encnum);
            }

            func("flushed %u bytes closing video encoder", encnum);

        } while(encnum > 0);
        free(encbuf);
    }
    // close the filedump
    if(filedump_fd) fclose(filedump_fd);

    // now deallocate the ringbuffer
    ringbuffer_free(ringbuffer);

    shout_close(ice);
    //  shout_sync(ice);
    //  shout_free(ice);
    shout_shutdown();

    if(enc_y) free(enc_y);
    if(enc_u) free(enc_u);
    if(enc_v) free(enc_v);
    if(enc_yuyv) free(enc_yuyv);

    free(fps);
}
/* Get read pointer at most `cnt' bytes from `rb' to
   `dest'.  Returns the actual readable number of bytes . */
size_t ringbuffer_get_readpointer (ringbuffer_t * rb, uint8_t **dest, size_t cnt)
{
	size_t free_cnt;
	size_t cnt2;
	size_t to_read;
	size_t n1, n2;
	size_t tmp_read_ptr = rb->read_ptr;

	if ((free_cnt = ringbuffer_read_space (rb)) == 0)
		return 0;

	to_read = cnt > free_cnt ? free_cnt : cnt;

	cnt2 = rb->read_ptr + to_read;

	if (cnt2 > rb->size)
	{
		n1 = rb->size - rb->read_ptr;
		n2 = cnt2 & rb->size_mask;
	}
	else
	{
		n1 = to_read;
		n2 = 0;
	}
	if (n2)
	{
		if (to_read > rb->helpbufsize)
		{
			rb->helpbufsize = to_read;
			rb->helpbuf = realloc (rb->helpbuf, rb->helpbufsize);
		}
		memcpy (rb->helpbuf, &(rb->buf[rb->read_ptr]), n1);
		tmp_read_ptr += n1;
		tmp_read_ptr &= rb->size_mask;
		memcpy (rb->helpbuf + n1, &(rb->buf[tmp_read_ptr]), n2);
		*dest = rb->helpbuf;
	}
	else
		*dest = &(rb->buf[rb->read_ptr]);

	return to_read;
}
/* The copying data reader.  Copy at most `cnt' bytes from `rb' to
 * `dest'.  Returns the actual number of bytes copied.
 */
size_t ringbuffer_read (ringbuffer_t * rb, uint8_t *dest, size_t cnt)
{
	size_t free_cnt;
	size_t cnt2;
	size_t to_read;
	size_t n1, n2;

	if ((free_cnt = ringbuffer_read_space (rb)) == 0)
		return 0;

	to_read = cnt > free_cnt ? free_cnt : cnt;

	cnt2 = rb->read_ptr + to_read;

	if (cnt2 > rb->size)
	{
		n1 = rb->size - rb->read_ptr;
		n2 = cnt2 & rb->size_mask;
	}
	else
	{
		n1 = to_read;
		n2 = 0;
	}

	memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
	rb->read_ptr += n1;
	rb->read_ptr &= rb->size_mask;

	if (n2)
	{
		memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
		rb->read_ptr += n2;
		rb->read_ptr &= rb->size_mask;
	}

	return to_read;
}
示例#4
0
void VideoEncoder::thread_loop() {
    int encnum;
    int res;
    auto screen = this->screen.lock();

    /* Convert picture from rgb to yuv420 planar

       two steps here:

       1) rgb24a or bgr24a to yuv422 interlaced (yuyv)
       2) yuv422 to yuv420 planar (yuv420p)

       to fix endiannes issues try adding #define ARCH_PPC
       and using
       mlt_convert_bgr24a_to_yuv422
       or
       mlt_convert_argb_to_yuv422
       (see mlt_frame.h in mltframework.org sourcecode)
       i can't tell as i don't have PPC, waiting for u mr.goil :)
     */

    uint8_t *surface = (uint8_t *)screen->get_surface();
    time_t *tm = (time_t *)malloc(sizeof(time_t));
    time(tm);
//   std::cerr << "-- ENC:" << asctime(localtime(tm));
    if(!surface) {
        fps->delay();
        /* std::cout << "fps->start_tv.tv_sec :" << fps->start_tv.tv_sec << \
           " tv_usec :" << fps->start_tv.tv_usec << "   \r" << std::endl; */
        return;
    }
    fps->delay();
    //uncomment this to see how long it takes between two frames in us.
    /*    timeval start_t;
        gettimeofday(&start_t,NULL);
        timeval did;
        timersub(&start_t, &m_lastTime, &did);
        m_lastTime.tv_sec = start_t.tv_sec;
        m_lastTime.tv_usec = start_t.tv_usec;
        std::cerr << "diff time :" << did.tv_usec << std::endl;*/
    screen->lock();
    auto & geo = screen->getGeometry();
    switch(screen->get_pixel_format()) {
    case ViewPort::RGBA32:
        mlt_convert_rgb24a_to_yuv422(surface,
                                     geo.getSize().x(), geo.getSize().y(),
                                     geo.getSize().x() << 2, (uint8_t*)enc_yuyv, NULL);
        break;

    case ViewPort::BGRA32:
        mlt_convert_bgr24a_to_yuv422(surface,
                                     geo.getSize().x(), geo.getSize().y(),
                                     geo.getSize().x() << 2, (uint8_t*)enc_yuyv, NULL);
        break;

    case ViewPort::ARGB32:
        mlt_convert_argb_to_yuv422(surface,
                                   geo.getSize().x(), geo.getSize().y(),
                                   geo.getSize().x() << 2, (uint8_t*)enc_yuyv, NULL);
        break;

    default:
        error("Video Encoder %s doesn't supports Screen %s pixel format",
              name.c_str(), screen->getName().c_str());
    }

    screen->unlock();

    ccvt_yuyv_420p(geo.getSize().x(), geo.getSize().y(), enc_yuyv, enc_y, enc_u, enc_v);

    ////// got the YUV, do the encoding
    res = encode_frame();
    if(res != 0) error("Can't encode frame");

    /// proceed writing and streaming encoded data in encpipe

    encnum = 0;
    if(write_to_disk || write_to_stream) {
        if((encnum = ringbuffer_read_space(ringbuffer)) > 0) {
            encbuf = (char *)realloc(encbuf, encnum);
//      encbuf = (char *)realloc(encbuf, (((audio_kbps + video_kbps)*1024)/24)); //doesn't change anything for shifting problem
            encnum = ringbuffer_read(ringbuffer, encbuf, encnum);
//      encnum = ringbuffer_read(ringbuffer, encbuf,
//                             ((audio_kbps + video_kbps)*1024)/24);
        }
    }

    if(encnum > 0) {
        //      func("%s has encoded %i bytes", name, encnum);
        if(write_to_disk && filedump_fd)
            fwrite(encbuf, 1, encnum, filedump_fd);

        if(write_to_stream && ice) {
            /*	int	wait_ms;
                wait_ms = shout_delay(ice);
                std::cerr << "---- shout delay :" << wait_ms << std::endl;*/
            shout_sync(ice);
            if(shout_send(ice, (const unsigned char*)encbuf, encnum)
               != SHOUTERR_SUCCESS) {
                error("shout_send: %s", shout_get_error(ice));
            } // else
              //printf("%d %d\n", encnum, (int)shout_queuelen(ice));
        }
        gettimeofday(&m_ActualTime, NULL);
        if(m_ActualTime.tv_sec == m_OldTime.tv_sec)
            m_ElapsedTime += ((double)(m_ActualTime.tv_usec - m_OldTime.tv_usec)) / 1000000.0;
        else
            m_ElapsedTime += ((double)(m_ActualTime.tv_sec - m_OldTime.tv_sec)) + \
                             (((double)(m_ActualTime.tv_usec - m_OldTime.tv_usec)) / 1000000.0);
        m_OldTime.tv_sec = m_ActualTime.tv_sec;
        m_OldTime.tv_usec = m_ActualTime.tv_usec;
        m_Streamed += encnum;
        if(m_ElapsedTime >= 3.0) {      //calculate stream rate every minimum 3 seconds
            m_StreamRate = ((double)m_Streamed / m_ElapsedTime) / 1000.0;
            m_ElapsedTime = 0;
            m_Streamed = 0;
        }
    }
}
示例#5
0
文件: audio_jack.cpp 项目: K0F/FreeJ
int JackClient::Process(jack_nframes_t nframes, void *self) {
    int j = 0;
    bool isEncoded = ((JackClient*) self)->m_Encoded;

    for(std::map<int, JackPort*>::iterator i = m_InputPortMap.begin();
        i != m_InputPortMap.end(); i++) {
        if(jack_port_connected(i->second->Port)) {
            sample_t *in = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
//                memcpy (i->second->Buf, in, sizeof (sample_t) * m_BufferSize); //m_BufferSize -> 2nd AudioCollector parameter
            //Buff attribué par SetInputBuf dans le construcAteur de AudioCollector
            if(isEncoded) {     //Added this to write in the buffer only if
                //the encoder is in action
                if(!j) {        //only streams the 1st Jack Input port
                    if(ringbuffer_write_space(((JackClient*) self)->first) >= (sizeof(sample_t) * nframes)) {
                        ringbuffer_write(((JackClient*) self)->first, (char *)in, (sizeof(sample_t) * nframes));
                    }
                    /*		    else
                                    {
                                      std::cerr << "-----------Pas suffisament de place dans audio_fred !!!" << std::endl;
                                    }*/
                    j++;
                }
            }
        }
    }

    int channels = ((JackClient*) self)->m_ringbufferchannels;


    bool output_available = false;
//m_ringbuffer created by ViewPort::add_audio
//1024*512 rounded up to the next power of two.
    if(((JackClient*) self)->m_ringbuffer) {
//        static int firsttime = 1 + ceil(4096/nframes); // XXX pre-buffer  TODO decrease this and compensate latency

        if(ringbuffer_read_space(((JackClient*) self)->m_ringbuffer) >=
           /*firsttime */ channels * nframes * sizeof(float)) {
//                firsttime=1;
            size_t rv = ringbuffer_read(((JackClient*) self)->m_ringbuffer,
                                        ((JackClient*) self)->m_inbuf,
                                        channels * nframes * sizeof(float));
            if(isEncoded) {     //Added this to write in the buffer only if
                //the encoder is in action
                if(ringbuffer_write_space(((JackClient*) self)->audio_mix_ring) >= rv) {
//                      unsigned char *aPtr = (unsigned char *)((JackClient*) self)->m_inbuf;
                    size_t rf = ringbuffer_write(((JackClient*) self)->audio_mix_ring, ((JackClient*) self)->m_inbuf, rv);
                    if(rf != rv)
                        std::cerr << "---" << rf << " : au lieu de :" << rv << " octets ecrits dans le ringbuffer !!" \
                                  << std::endl;
                } else {
                    std::cerr << "-----------Not enough room in audio_mix_ring !!!" << std::endl;
                }
            }
//reads m_ringbuffer and puts it in m_inbuf
//m_inbuf created in SetRingbufferPtr called by add_audio
//4096 * channels * sizeof(float)
            if(rv >= channels * nframes * sizeof(float)) {
                output_available = true;
            }
        }
#if 0
        else if(firsttime == 1)
            fprintf(stderr, "AUDIO BUFFER UNDERRUN: %i samples < %i\n", ringbuffer_read_space(((JackClient*) self)->m_ringbuffer) / sizeof(float) / channels, nframes);
#endif
    }

    j = 0;
    for(std::map<int, JackPort*>::iterator i = m_OutputPortMap.begin();
        i != m_OutputPortMap.end(); i++) {
        if(output_available && j < channels) {
            sample_t *out = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
            memset(out, 0, sizeof(jack_default_audio_sample_t) * nframes);
            deinterleave(((JackClient*) self)->m_inbuf, out, channels
                         , j, nframes);
//writes nframes of channels m_inbuf to out
//two times if stereo (shifted by the channel number)
#if 0                   // test-noise:
            int i;
            for(i = 0; i < nframes; i++) out[i] = (float) i / (float)nframes;
#endif
        } else { // no output availaible, clear
            sample_t *out = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
            memset(out, 0, sizeof(sample_t) * nframes);
        }
        j++;
    }

    m_BufferSize = nframes;

//      if(RunCallback&&RunContext)
//      {
//              // do the work
//              RunCallback(RunContext, nframes);
//      }

    return 0;
}