static void * winsnd_thread(void *p){ MSSndCard *card=(MSSndCard*)p; WinSndData *d=(WinSndData*)card->data; int bsize=d->rate/8000 * 320; uint8_t *rtmpbuff=NULL; uint8_t *wtmpbuff=NULL; int err; MMRESULT mr = NOERROR; int pos_whdr=0; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->sound_err=winsnd_open(d, d->devid, d->bits,d->stereo,d->rate,&bsize); if (d->sound_err==0){ rtmpbuff=(uint8_t*)alloca(bsize); wtmpbuff=(uint8_t*)alloca(bsize); } while(d->read_started || d->write_started){ if (d->sound_err==0){ if (d->write_started){ #if 0 if (d->stat_output>0 && d->buffer_playing==0) { ms_error("No data currently playing in sound card" ); } if (d->stat_output>0 && (d->stat_input-d->stat_output>10 || d->stat_input-d->stat_output<-10)) ms_error("Not perfectly synchronized (input-output=%i)", d->stat_input-d->stat_output); #endif while (d->buffer_playing<6 && d->buffer_playing<MAX_WAVEHDR) { ms_mutex_lock(&d->mutex); err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); ms_mutex_unlock(&d->mutex); if (err!=bsize) break; ms_mutex_lock(&d->mutex); /* write to sound devide! */ memcpy (d->waveouthdr[pos_whdr].lpData, wtmpbuff, bsize); mr = waveOutWrite (d->waveoutdev, &(d->waveouthdr[pos_whdr]), sizeof (d->waveouthdr[pos_whdr])); if (mr != MMSYSERR_NOERROR) { if (mr == WAVERR_STILLPLAYING) { /* retry later */ /* data should go back to queue */ /* TODO */ ms_warning("sound device write STILL_PLAYING (waveOutWrite:0x%i)", mr); } else { ms_warning("sound device write returned (waveOutWrite:0x%i)", mr); } } else { d->buffer_playing++; pos_whdr++; if (pos_whdr == MAX_WAVEHDR) pos_whdr = 0; /* loop over the prepared blocks */ } ms_mutex_unlock(&d->mutex); if (err<0){ #if !defined(_WIN32_WCE) ms_warning("Fail to write %i bytes from soundcard: %s", bsize,strerror(errno)); #else ms_warning("Fail to write %i bytes from soundcard: %i", bsize,WSAGetLastError()); #endif } } if (d->buffer_playing==6 || d->buffer_playing==MAX_WAVEHDR) { int discarded=0; ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; d->stat_notplayed++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20*320)/320, d->buffer_playing, d->stat_input - d->stat_output); } #if !defined(_WIN32_WCE) Sleep(5); #endif #if defined(_WIN32_WCE) Sleep(10); #endif }else { int discarded=0; /* don't think this is usefull, anyway... */ ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20)/320, d->buffer_playing, d->stat_input - d->stat_output); Sleep(10); } }else Sleep(10); } if (d->sound_err==0) { int i; int count=0; /* close sound card */ ms_error("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->buffer_playing, d->stat_input - d->stat_output, d->stat_notplayed); /* unprepare buffer */ for (i = 0; i < MAX_WAVEHDR; i++) { int counttry=0; for (counttry=0;counttry<10;counttry++) { mr = waveInUnprepareHeader (d->waveindev, &(d->waveinhdr[i]), sizeof (d->waveinhdr[i])); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i", count, mr); Sleep (20); } else { count++; ms_message("successfully unprepared %i buffer from sound card.", count); break; } } } ms_warning("unprepared %i buffer from sound card.", count); mr = waveInStop (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_error("failed to stop recording sound card (waveInStop:0x%i)", mr); } else { ms_message("successfully stopped recording sound card"); } mr = waveInReset (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to reset recording sound card (waveInReset:0x%i)", mr); } else { ms_message("successful reset of recording sound card"); } mr = waveInClose (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to close recording sound card (waveInClose:0x%i)", mr); } else { ms_message("successfully closed recording sound card"); } d->sound_err=-1; } d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; return NULL; }
static void * alsa_write_thread(void *p){ AlsaReadData *ad=(AlsaReadData*)p; int samples=(160*ad->rate)/8000; int err; int count=0; mblk_t *om=NULL; struct timeval timeout; if (ad->handle==NULL && ad->pcmdev!=NULL){ ad->handle=alsa_open_r(ad->pcmdev,16,ad->nchannels==2,ad->rate); } if (ad->handle==NULL) return NULL; while (ad->read_started) { count = alsa_can_read(ad->handle,samples); if (count==24) { /* keep this value for this driver */ } else if (count<=0) { count = samples; } else if (count>0) { //ms_warning("%i count", count); //count = samples; } int size=count*2; om=allocb(size,0); if ((err=alsa_read(ad->handle,om->b_wptr,count))<=0) { ms_warning("nothing to read"); //ms_warning("Fail to read samples %i", count); freemsg(om); /* leak fixed */ continue; } //ms_warning(" read %i", err); size=err*2; om->b_wptr+=size; ms_mutex_lock(&ad->mutex); ms_bufferizer_put(ad->bufferizer,om); ms_mutex_unlock(&ad->mutex); if (count==24) { timeout.tv_sec = 0; timeout.tv_usec = 2000; select(0, 0, NULL, NULL, &timeout ); } else { /* select will be less active than locking on "read" */ timeout.tv_sec = 0; timeout.tv_usec = 5000; select(0, 0, NULL, NULL, &timeout ); } } if (ad->handle!=NULL) snd_pcm_close(ad->handle); ad->handle=NULL; return NULL; }
static void CALLBACK WaveInCallback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { WAVEHDR *wHdr; MMRESULT mr = NOERROR; WinSndData *device; device = (WinSndData *)dwInstance; switch (uMsg) { case MM_WOM_DONE: wHdr = (WAVEHDR *) dwParam1; /* A waveform-audio data block has been played and can now be freed. */ ms_message("WaveInCallback : MM_WOM_DONE"); waveInUnprepareHeader (waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR)); break; case WIM_OPEN: ms_message("WaveInCallback : WIM_OPEN"); break; case WIM_CLOSE: ms_message("WaveInCallback : WIM_CLOSE"); break; case WIM_DATA: wHdr = (WAVEHDR *) dwParam1; device->bytes_read+=wHdr->dwBytesRecorded; if (!device->read_started && !device->write_started) { mr = waveInUnprepareHeader (device->waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR)); ms_warning("WaveInCallback : unprepare header (waveInUnprepareHeader:0x%i)", mr); return; } if (wHdr->dwBufferLength!=wHdr->dwBytesRecorded) { mr = waveInAddBuffer (device->waveindev, wHdr, sizeof (device->waveinhdr[wHdr->dwUser])); if (mr != MMSYSERR_NOERROR) { ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr); } return; } ms_mutex_lock(&device->mutex); if (device->read_started) { mblk_t *rm=NULL; if (rm==NULL) rm=allocb(wHdr->dwBufferLength,0); memcpy(rm->b_wptr,wHdr->lpData, wHdr->dwBufferLength); #ifndef DISABLE_SPEEX if (device->pst!=NULL) { int vad; //memset(rm->b_wptr,0, wHdr->dwBufferLength); vad = speex_preprocess(device->pst, (short*)rm->b_wptr, NULL); #if 0 if (vad!=1) ms_message("WaveInCallback : %d", vad); #endif } #endif rm->b_wptr+=wHdr->dwBufferLength; putq(&device->rq,rm); device->stat_input++; rm=NULL; } ms_mutex_unlock(&device->mutex); mr = waveInAddBuffer (device->waveindev, wHdr, sizeof (device->waveinhdr[wHdr->dwUser])); if (mr != MMSYSERR_NOERROR) { ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr); return; } } }
static void itc_source_queue_packet(MSFilter *f, mblk_t *m){ SourceState *s=(SourceState *)f->data; ms_mutex_lock(&s->mutex); ms_queue_put(&s->q,m); ms_mutex_unlock(&s->mutex); }
static void eof_callback(void *user_data) { Eof *obj = (Eof *)user_data; ms_mutex_lock(&obj->mutex); obj->eof = TRUE; ms_mutex_unlock(&obj->mutex); }
static int video_capture_set_vsize(MSFilter *f, void* data){ AndroidReaderContext* d = (AndroidReaderContext*) f->data; ms_mutex_lock(&d->mutex); d->requestedSize=*(MSVideoSize*)data; // always request landscape mode, orientation is handled later if (d->requestedSize.height > d->requestedSize.width) { int tmp = d->requestedSize.height; d->requestedSize.height = d->requestedSize.width; d->requestedSize.width = tmp; } JNIEnv *env = ms_get_jni_env(); jmethodID method = env->GetStaticMethodID(d->helperClass,"selectNearestResolutionAvailable", "(III)[I"); // find neareast hw-available resolution (using jni call); jobject resArray = env->CallStaticObjectMethod(d->helperClass, method, ((AndroidWebcamConfig*)d->webcam->data)->id, d->requestedSize.width, d->requestedSize.height); if (!resArray) { ms_error("Failed to retrieve camera '%d' supported resolutions\n", ((AndroidWebcamConfig*)d->webcam->data)->id); return -1; } // handle result : // - 0 : width // - 1 : height // - 2 : useDownscaling jint res[3]; env->GetIntArrayRegion((jintArray)resArray, 0, 3, res); ms_message("Camera selected resolution is: %dx%d (requested: %dx%d) with downscaling?%d\n", res[0], res[1], d->requestedSize.width, d->requestedSize.height, res[2]); d->hwCapableSize.width = res[0]; d->hwCapableSize.height = res[1]; d->useDownscaling = res[2]; int rqSize = d->requestedSize.width * d->requestedSize.height; int hwSize = d->hwCapableSize.width * d->hwCapableSize.height; double downscale = d->useDownscaling ? 0.5 : 1; // if hw supplies a smaller resolution, modify requested size accordingly if ((hwSize * downscale * downscale) < rqSize) { ms_message("Camera cannot produce requested resolution %dx%d, will supply smaller one: %dx%d\n", d->requestedSize.width, d->requestedSize.height, (int) (res[0] * downscale), (int) (res[1]*downscale)); d->requestedSize.width = (int) (d->hwCapableSize.width * downscale); d->requestedSize.height = (int) (d->hwCapableSize.height * downscale); } else if ((hwSize * downscale * downscale) > rqSize) { ms_message("Camera cannot produce requested resolution %dx%d, will capture a bigger one (%dx%d) and crop it to match encoder requested resolution\n", d->requestedSize.width, d->requestedSize.height, (int)(res[0] * downscale), (int)(res[1] * downscale)); } // is phone held |_ to cam orientation ? if (d->rotation == UNDEFINED_ROTATION || compute_image_rotation_correction(d, d->rotation) % 180 != 0) { if (d->rotation == UNDEFINED_ROTATION) { ms_error("To produce a correct image, Mediastreamer MUST be aware of device's orientation BEFORE calling 'configure_video_source'\n"); ms_warning("Capture filter do not know yet about device's orientation.\n" "Current assumption: device is held perpendicular to its webcam (ie: portrait mode for a phone)\n"); d->rotationSavedDuringVSize = 0; } else { d->rotationSavedDuringVSize = d->rotation; } bool camIsLandscape = d->hwCapableSize.width > d->hwCapableSize.height; bool reqIsLandscape = d->requestedSize.width > d->requestedSize.height; // if both are landscape or both portrait, swap if (camIsLandscape == reqIsLandscape) { int t = d->requestedSize.width; d->requestedSize.width = d->requestedSize.height; d->requestedSize.height = t; ms_message("Swapped resolution width and height to : %dx%d\n", d->requestedSize.width, d->requestedSize.height); } } else { d->rotationSavedDuringVSize = d->rotation; } ms_mutex_unlock(&d->mutex); return 0; }
void ms_ticker_get_last_late_tick(MSTicker *ticker, MSTickerLateEvent *ev){ bool_t need_lock = ms_thread_self() != ticker->thread_id; if (need_lock) ms_mutex_lock(&ticker->lock); memcpy(ev,&ticker->late_event,sizeof(MSTickerLateEvent)); if (need_lock) ms_mutex_unlock(&ticker->lock); }
static void au_write_put(AUWrite *d, mblk_t *m){ ms_mutex_lock(&d->common.mutex); ms_bufferizer_put(d->buffer,m); ms_mutex_unlock(&d->common.mutex); }
static void conf_process(MSFilter *f){ int i; ConfState *s=(ConfState*)f->data; Channel *chan; Channel *chan0; ms_mutex_lock(&s->lock); /*read from all inputs and put into bufferizers*/ for (i=0;i<CONF_MAX_PINS;++i){ if (f->inputs[i]!=NULL){ chan=&s->channels[i]; ms_bufferizer_put_from_queue(&chan->buff,f->inputs[i]); if (ms_bufferizer_get_avail(&chan->buff)>0) { chan->missed=0; /* reset counter of missed packet */ if (/*i>0 && */chan->is_used==FALSE) { chan->is_used=TRUE; ms_message("msconf: new contributing stream (chan=%i) %i", ms_bufferizer_get_avail(&chan->buff), i); } } } } /*do the job */ while(should_process(f,s)==TRUE){ conf_sum(f, s); conf_dispatch(f,s); } #if 0 /* mixer is disabled! -> copy A->B and B->A*/ if (s->mix_mode == FALSE) { /* get the soundread data and copy it to pinX */ for (i=1;i<CONF_MAX_PINS;i=i+2){ if (f->inputs[i]!=NULL){ chan0=&s->channels[0]; chan=&s->channels[i]; if (chan->is_used==TRUE) { while (ms_bufferizer_read(&chan->buff,(uint8_t*)chan->input,s->conf_gran)==s->conf_gran) { if (f->outputs[0]!=NULL) { /* send in pin0 */ mblk_t *m=allocb(s->conf_gran,0); memcpy(m->b_wptr, chan->input, s->conf_gran); m->b_wptr+=s->conf_gran; ms_queue_put(f->outputs[0],m); } } } if (chan0->is_used==TRUE) { while (ms_bufferizer_read(&chan0->buff,(uint8_t*)chan0->input,s->conf_gran)==s->conf_gran) { if (f->outputs[i]!=NULL) { /* send in pinI */ mblk_t *m=allocb(s->conf_gran,0); memcpy(m->b_wptr, chan0->input, s->conf_gran); m->b_wptr+=s->conf_gran; ms_queue_put(f->outputs[i],m); } } } break; } } } #endif // 0 ms_mutex_unlock(&s->lock); }
pascal OSErr sgdata_callback(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon) { #pragma unused(offset,chRefCon,time,writeType) CodecFlags ignore; V4lState *s=(V4lState *)refCon; ComponentResult err = noErr; if (!s) goto bail; Rect boundsRect = {0, 0, s->vsize.height, s->vsize.width}; /* 240 , 320*/ if (s->pgworld) { if (s->decomseq == 0) { Rect sourceRect = { 0, 0 }; MatrixRecord scaleMatrix; ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(0); err = SGGetChannelSampleDescription(c,(Handle)imageDesc); BailErr(err); // make a scaling matrix for the sequence sourceRect.right = (**imageDesc).width; sourceRect.bottom = (**imageDesc).height; RectMatrix(&scaleMatrix, &sourceRect, &boundsRect); err = DecompressSequenceBegin(&s->decomseq, // pointer to field to receive unique ID for sequence imageDesc, // handle to image description structure s->pgworld, // port for the DESTINATION image NULL, // graphics device handle, if port is set, set to NULL NULL, // source rectangle defining the portion of the image to decompress &scaleMatrix, // transformation matrix srcCopy, // transfer mode specifier NULL, // clipping region in dest. coordinate system to use as a mask 0, // flags codecNormalQuality, // accuracy in decompression bestSpeedCodec); // compressor identifier or special identifiers ie. bestSpeedCodec BailErr(err); DisposeHandle((Handle)imageDesc); imageDesc = NULL; } // decompress a frame into the GWorld - can queue a frame for async decompression when passed in a completion proc // once the image is in the GWorld it can be manipulated at will err = DecompressSequenceFrameS(s->decomseq, // sequence ID returned by DecompressSequenceBegin p, // pointer to compressed image data len, // size of the buffer 0, // in flags &ignore, // out flags NULL); // async completion proc BailErr(err); { unsigned line; mblk_t *buf; int size = s->vsize.width * s->vsize.height * 3; buf=allocb(size,0); PixMap * pixmap = *GetGWorldPixMap(s->pgworld); uint8_t * data; unsigned rowBytes = pixmap->rowBytes & (((unsigned short) 0xFFFF) >> 2); unsigned pixelSize = pixmap->pixelSize / 8; // Pixel size in bytes unsigned lineOffset = rowBytes - s->vsize.width * pixelSize; data = (uint8_t *) GetPixBaseAddr(GetGWorldPixMap(s->pgworld)); for (line = 0 ; line < s->vsize.height ; line++) { unsigned offset = line * (s->vsize.width * pixelSize + lineOffset); memcpy(buf->b_wptr + ((line * s->vsize.width) * pixelSize), data + offset, (rowBytes - lineOffset)); } if (s->pix_fmt==MS_RGB24) { /* Conversion from top down bottom up (BGR to RGB and flip) */ unsigned long Index,nPixels; unsigned char *blue; unsigned char tmp; short iPixelSize; blue=buf->b_wptr; nPixels=s->vsize.width*s->vsize.height; iPixelSize=24/8; for(Index=0;Index!=nPixels;Index++) // For each pixel { tmp=*blue; *blue=*(blue+2); *(blue+2)=tmp; blue+=iPixelSize; } } buf->b_wptr+=size; ms_mutex_lock(&s->mutex); putq(&s->rq, buf); ms_mutex_unlock(&s->mutex); } } bail: return err; }