rendered paste bodyIndex: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp (revision 26445)
+++ libs/libmythtv/avformatdecoder.cpp (working copy)
@@ -126,6 +126,8 @@
void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src,
int offset[4], int y, int type, int height);
+AVStream *videostream = NULL;
+
static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id)
{
AVCodec *codec = c;
@@ -2969,6 +2971,8 @@
AVFrame mpa_pic;
avcodec_get_frame_defaults(&mpa_pic);
+ videostream = curstream;
+
avcodeclock->lock();
if (private_dec)
{
@@ -3006,9 +3010,11 @@
if (!gotpicture)
{
+ gotvideo = 1;
return true;
}
+//START
// Decode CEA-608 and CEA-708 captions
for (uint i = 0; i < (uint)mpa_pic.atsc_cc_len;
i += ((mpa_pic.atsc_cc_buf[i] & 0x1f) * 3) + 2)
@@ -3163,6 +3169,110 @@
return true;
}
+bool AvFormatDecoder::ProcessVideoFrame(AVStream *curstream, AVFrame *mpa_pic)
+{
+ int ret = 0, gotpicture = 0;
+ long long pts = 0;
+ AVCodecContext *context = curstream->codec;
+
+ // Decode CEA-608 and CEA-708 captions
+ for (uint i = 0; i < (uint)mpa_pic->atsc_cc_len;
+ i += ((mpa_pic->atsc_cc_buf[i] & 0x1f) * 3) + 2)
+ {
+ DecodeDTVCC(mpa_pic->atsc_cc_buf + i,
+ mpa_pic->atsc_cc_len - i);
+ }
+
+ VideoFrame *picframe = (VideoFrame *)(mpa_pic->opaque);
+
+ if (!directrendering)
+ {
+ AVPicture tmppicture;
+
+ VideoFrame *xf = picframe;
+ picframe = GetPlayer()->GetNextVideoFrame(false);
+
+ unsigned char *buf = picframe->buf;
+ avpicture_fill(&tmppicture, buf, PIX_FMT_YUV420P, context->width,
+ context->height);
+ tmppicture.data[0] = buf + picframe->offsets[0];
+ tmppicture.data[1] = buf + picframe->offsets[1];
+ tmppicture.data[2] = buf + picframe->offsets[2];
+ tmppicture.linesize[0] = picframe->pitches[0];
+ tmppicture.linesize[1] = picframe->pitches[1];
+ tmppicture.linesize[2] = picframe->pitches[2];
+
+ QSize dim = get_video_dim(*context);
+ sws_ctx = sws_getCachedContext(sws_ctx, context->width,
+ context->height, context->pix_fmt,
+ context->width, context->height,
+ PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
+ NULL, NULL, NULL);
+ if (!sws_ctx)
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate sws context");
+ return false;
+ }
+ sws_scale(sws_ctx, mpa_pic->data, mpa_pic->linesize, 0, dim.height(),
+ tmppicture.data, tmppicture.linesize);
+
+
+ if (xf)
+ {
+ // Set the frame flags, but then discard it
+ // since we are not using it for display.
+ xf->interlaced_frame = mpa_pic->interlaced_frame;
+ xf->top_field_first = mpa_pic->top_field_first;
+ xf->frameNumber = framesPlayed;
+ GetPlayer()->DiscardVideoFrame(xf);
+ }
+ }
+ else if (!picframe)
+ {
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "NULL videoframe - direct rendering not"
+ "correctly initialized.");
+ return false;
+ }
+
+ pts = (long long)(av_q2d(curstream->time_base) * mpa_pic->reordered_opaque * 1000);
+
+ long long temppts = pts;
+
+ // Validate the video pts against the last pts. If it's
+ // a little bit smaller, equal or missing, compute
+ // it from the last. Otherwise assume a wraparound.
+ if (!ringBuffer->isDVD() &&
+ temppts <= lastvpts &&
+ (temppts + 10000 > lastvpts || temppts <= 0))
+ {
+ temppts = lastvpts;
+ temppts += (long long)(1000 / fps);
+ // MPEG2/H264 frames can be repeated, update pts accordingly
+ temppts += (long long)(mpa_pic->repeat_pict * 500 / fps);
+ }
+
+ VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC +
+ QString("ProcessVideoFrame timecode %1 %2 %3").arg(mpa_pic->reordered_opaque).arg(temppts).arg(lastvpts));
+
+ picframe->interlaced_frame = mpa_pic->interlaced_frame;
+ picframe->top_field_first = mpa_pic->top_field_first;
+ picframe->repeat_pict = mpa_pic->repeat_pict;
+
+ picframe->frameNumber = framesPlayed;
+ GetPlayer()->ReleaseNextVideoFrame(picframe, temppts);
+ if (private_dec && mpa_pic->data[3])
+ context->release_buffer(context, mpa_pic);
+
+ decoded_video_frame = picframe;
+ gotvideo = 1;
+ framesPlayed++;
+
+ lastvpts = temppts;
+
+ return true;
+}
+
+
/** \fn AvFormatDecoder::ProcessVBIDataPacket(const AVStream*, const AVPacket*)
* \brief Process ivtv proprietary embedded vertical blanking
* interval captions.
@@ -4075,8 +4185,21 @@
{
othresh = ((ototal>>1) + (ototal>>2));
allowedquit = ofill > othresh;
+ VERBOSE(VB_PLAYBACK,
+ LOC + QString("AudioBuffer Full ofill %1 ototal %2 othresh %3")
+ .arg(ofill).arg(ototal).arg(othresh));
}
+ VERBOSE(VB_PLAYBACK, LOC + "GetFrame -- start");
+ if (private_dec && private_dec->HasBufferedFrames())
+ {
+ VERBOSE(VB_PLAYBACK, LOC + "Private Decoder has buffered frames available!");
+ AVFrame mpa_pic;
+ avcodec_get_frame_defaults(&mpa_pic);
+ private_dec->GetBufferedFrame(videostream, &mpa_pic);
+ ProcessVideoFrame(videostream, &mpa_pic);
+ }
+// allowedquit = false;
while (!allowedquit)
{
if ((decodetype & kDecodeAudio) &&
Index: libs/libmythtv/privatedecoder_crystalhd.h
===================================================================
--- libs/libmythtv/privatedecoder_crystalhd.h (revision 26445)
+++ libs/libmythtv/privatedecoder_crystalhd.h (working copy)
@@ -17,6 +17,29 @@
#include <libcrystalhd/libcrystalhd_if.h>
#include "privatedecoder.h"
+class PrivateDecoderCrystalHD;
+class RetrievalThread : public QThread
+{
+ Q_OBJECT
+
+ public:
+ RetrievalThread(PrivateDecoderCrystalHD *dec)
+ : QThread(NULL), m_dec(dec) { }
+
+ protected:
+ virtual void run(void);
+
+ private:
+ PrivateDecoderCrystalHD *m_dec;
+};
+
+typedef struct PacketBuffer_
+{
+ uint8_t *buf;
+ int size;
+ int64_t pts;
+} PacketBuffer;
+
enum BC_DEVICE_TYPE
{
BC_70012 = 0,
@@ -34,13 +57,17 @@
bool no_hardware_decode,
AVCodecContext *avctx);
virtual bool Reset(void);
+ virtual bool HasBufferedFrames(void);
+ virtual int GetBufferedFrame(AVStream *stream,
+ AVFrame *picture);
virtual int GetFrame(AVStream *stream,
AVFrame *picture,
int *got_picture_ptr,
AVPacket *pkt);
- void RetrieveFrame(void);
+ void RetrieveFrames(void);
private:
+ bool StartRetrievalThread(void);
bool CreateFilter(AVCodecContext *avctx);
void FillFrame(BC_DTS_PROC_OUT *out);
@@ -53,7 +80,13 @@
BC_DEVICE_TYPE m_device_type;
BC_OUTPUT_FORMAT m_pix_fmt;
QList<VideoFrame*> m_decoded_frames;
+ QList<PacketBuffer*> m_packet_buffers;
+ QMutex m_decoded_frames_lock;
+ RetrievalThread *m_retrieval_thread;
+ bool m_pause_retrieval;
+ bool m_kill_retrieval;
VideoFrame *m_frame;
+ PacketBuffer *m_buffer;
AVBitStreamFilterContext *m_filter;
};
Index: libs/libmythtv/privatedecoder_crystalhd.cpp
===================================================================
--- libs/libmythtv/privatedecoder_crystalhd.cpp (revision 26445)
+++ libs/libmythtv/privatedecoder_crystalhd.cpp (working copy)
@@ -5,6 +5,16 @@
#define ERR QString("CrystalHD Err: ")
#define WARN QString("CrystalHD Warn: ")
+void RetrievalThread::run(void)
+{
+ if (!m_dec)
+ return;
+
+ VERBOSE(VB_PLAYBACK, LOC + QString("Starting retrieval thread."));
+ m_dec->RetrieveFrames();
+ VERBOSE(VB_PLAYBACK, LOC + QString("Stopping retrieval thread."));
+}
+
PixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt);
QString device_to_string(BC_DEVICE_TYPE device);
QString bcmerr_to_string(BC_STATUS err);
@@ -31,12 +41,30 @@
PrivateDecoderCrystalHD::PrivateDecoderCrystalHD()
: m_device(NULL), m_device_type(BC_70012),
- m_pix_fmt(OUTPUT_MODE_INVALID), m_frame(NULL), m_filter(NULL)
+ m_pix_fmt(OUTPUT_MODE_INVALID), m_decoded_frames_lock(QMutex::Recursive),
+ m_retrieval_thread(NULL), m_pause_retrieval(true), m_kill_retrieval(false),
+ m_frame(NULL), m_filter(NULL)
+
{
}
PrivateDecoderCrystalHD::~PrivateDecoderCrystalHD()
{
+ if (m_retrieval_thread)
+ {
+ m_pause_retrieval = true;
+ m_kill_retrieval = true;
+ int tries = 0;
+ while (!m_retrieval_thread->wait(100) && (tries++ < 50))
+ VERBOSE(VB_PLAYBACK, WARN + "Waited 100ms for retrieval to stop");
+
+ if (m_retrieval_thread->isRunning())
+ VERBOSE(VB_IMPORTANT, ERR + "Failed to stop retrieval.");
+ else
+ VERBOSE(VB_PLAYBACK, LOC + "Stopped frame retrieval.");
+ delete m_retrieval_thread;
+ }
+
if (m_filter)
av_bitstream_filter_close(m_filter);
@@ -64,7 +92,7 @@
static bool debugged = false;
uint32_t well_documented = DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW |
- DTS_SINGLE_THREADED_MODE | DTS_SKIP_TX_CHK_CPB |
+ DTS_SKIP_TX_CHK_CPB |
DTS_PLAYBACK_DROP_RPT_MODE |
DTS_DFLT_RESOLUTION(vdecRESOLUTION_CUSTOM);
INIT_ST
@@ -225,7 +253,7 @@
BC_INPUT_FORMAT fmt;
memset(&fmt, 0, sizeof(BC_INPUT_FORMAT));
- fmt.OptFlags = 0x80000000 | vdecFrameRateUnknown | 0x80;
+ fmt.OptFlags = 0x80000000 | vdecFrameRateUnknown;// | 0x80;
fmt.width = avctx->coded_width;
fmt.height = avctx->coded_height;
fmt.Progressive = 1;
@@ -313,8 +341,22 @@
}
}
+void inline free_buffer(PacketBuffer* buffer)
+{
+ if (buffer)
+ {
+ if (buffer->buf)
+ delete [] buffer->buf;
+ delete buffer;
+ }
+}
+
bool PrivateDecoderCrystalHD::Reset(void)
{
+ // FIXME actually need to make sure this has stopped before continuing
+ m_pause_retrieval = true;
+
+ QMutexLocker lock(&m_decoded_frames_lock);
free_frame(m_frame);
m_frame = NULL;
@@ -322,6 +364,10 @@
free_frame(m_decoded_frames[i]);
m_decoded_frames.clear();
+ for (int i = 0; i < m_packet_buffers.size(); i++)
+ free_buffer(m_packet_buffers[i]);
+ m_packet_buffers.clear();
+
if (!m_device)
return true;
@@ -331,6 +377,42 @@
return true;;
}
+bool PrivateDecoderCrystalHD::HasBufferedFrames()
+{
+ return m_decoded_frames.size() > 0;
+}
+
+int PrivateDecoderCrystalHD::GetBufferedFrame(AVStream *stream,
+ AVFrame *picture)
+{
+ AVCodecContext *avctx = stream->codec;
+ if (avctx->get_buffer(avctx, picture) < 0)
+ {
+ VERBOSE(VB_IMPORTANT, ERR +
+ QString("decoded frames available but no video buffers."));
+ return -1;
+ }
+
+ m_decoded_frames_lock.lock();
+ VideoFrame *frame = m_decoded_frames.takeLast();
+ m_decoded_frames_lock.unlock();
+
+ VERBOSE(VB_PLAYBACK, LOC +
+ QString("Output PTS timecode (%1) external").arg(frame->timecode * av_q2d(stream->time_base)));
+ picture->reordered_opaque = (int64_t)(frame->timecode / 1000);
+ picture->interlaced_frame = frame->interlaced_frame;
+ picture->top_field_first = frame->top_field_first;
+ picture->repeat_pict = frame->repeat_pict;
+ copy((VideoFrame*)picture->opaque, frame);
+ if (frame->priv[0] && frame->qstride)
+ {
+ memcpy(picture->atsc_cc_buf, frame->priv[0], frame->qstride);
+ picture->atsc_cc_len = frame->qstride;
+ }
+ free_frame(frame);
+ return 0;
+}
+
int PrivateDecoderCrystalHD::GetFrame(AVStream *stream,
AVFrame *picture,
int *got_picture_ptr,
@@ -344,8 +426,52 @@
if (!avctx)
return result;
- uint8_t* buf = pkt->data;
- int size = pkt->size;
+ if (!StartRetrievalThread())
+ return result;
+
+ m_buffer = new PacketBuffer();
+ m_buffer->buf = new unsigned char[pkt->size];
+ m_buffer->size = pkt->size;
+ m_buffer->pts = pkt->pts;
+ memcpy(m_buffer->buf, pkt->data, pkt->size);
+
+ if (!m_buffer)
+ return result;
+
+ m_packet_buffers.insert(0, m_buffer);
+ VERBOSE(VB_PLAYBACK, LOC +
+ QString("%1 packet buffers queued up").arg(m_packet_buffers.size()));
+ while (m_packet_buffers.size() > 0)
+ {
+
+ BC_DTS_STATUS drv_status;
+ INIT_ST
+ st = DtsGetDriverStatus(m_device, &drv_status);
+ CHECK_ST
+
+ if (drv_status.cpbEmptySize < 100000)
+ {
+ usleep(10000);
+ return 0;
+ }
+
+ PacketBuffer *buffer = m_packet_buffers.takeLast();
+
+// while (m_packet_buffers.size() > 30 && DtsTxFreeSize(m_device) < buffer->size)
+// usleep(10000);
+
+
+// if (DtsTxFreeSize(m_device) < buffer->size)
+// {
+// m_packet_buffers.append(buffer);
+// VERBOSE(VB_PLAYBACK, LOC +
+// QString("Buffer full %1 packet buffers queued up").arg(m_packet_buffers.size()));
+// usleep(10000);
+// return 0;
+// }
+
+ uint8_t* buf = buffer->buf;
+ int size = buffer->size;
bool free_buf = false;
int outbuf_size = 0;
uint8_t *outbuf = NULL;
@@ -374,43 +500,53 @@
}
+ usleep(5000);
+ int64_t timecode = (int64_t)(av_q2d(stream->time_base) * buffer->pts * 1000);
uint64_t chd_timestamp = 0; // msec units
- if (pkt->pts != (int64_t)AV_NOPTS_VALUE)
- chd_timestamp = (uint64_t)(av_q2d(stream->time_base) * pkt->pts * 1000);
-
+ if (buffer->pts != (int64_t)AV_NOPTS_VALUE)
+ chd_timestamp = (uint64_t)(buffer->pts * 1000);
+ VERBOSE(VB_PLAYBACK, LOC +
+ QString("Input PTS timecode (%1)").arg(timecode));
// TODO check for busy state and available buffer size
- INIT_ST
+ //INIT_ST
st = DtsProcInput(m_device, buf, size, chd_timestamp, false);
CHECK_ST
+ //CheckStatus();
- // TODO why is this needed - possibly overruning CrystalHD decoder or too
- // many buffered packets causing mythplayer problems?
- usleep(10000);
-
if (free_buf)
delete buf;
+ free_buffer(buffer);
if (!ok)
VERBOSE(VB_IMPORTANT, ERR + "Failed to send packet to decoder.");
- result = pkt->size;
+ result = buffer->size;
- RetrieveFrame();
+ }
- if (!m_decoded_frames.size())
+ m_decoded_frames_lock.lock();
+ int available = m_decoded_frames.size();
+ m_decoded_frames_lock.unlock();
+ if (!available)
+ {
return result;
+ }
if (avctx->get_buffer(avctx, picture) < 0)
{
VERBOSE(VB_IMPORTANT, ERR +
QString("%1 decoded frames available but no video buffers.")
- .arg(m_decoded_frames.size()));
+ .arg(available));
return -1;
}
+ m_decoded_frames_lock.lock();
VideoFrame *frame = m_decoded_frames.takeLast();
+ m_decoded_frames_lock.unlock();
+
+ VERBOSE(VB_PLAYBACK, LOC +
+ QString("Output PTS timecode (%1)").arg(frame->timecode * av_q2d(stream->time_base)));
*got_picture_ptr = 1;
- picture->reordered_opaque = (int64_t)(frame->timecode / av_q2d(stream->time_base)
- / 1000);
+ picture->reordered_opaque = (int64_t)(frame->timecode / 1000);
picture->interlaced_frame = frame->interlaced_frame;
picture->top_field_first = frame->top_field_first;
picture->repeat_pict = frame->repeat_pict;
@@ -424,40 +560,66 @@
return result;
}
-void PrivateDecoderCrystalHD::RetrieveFrame(void)
+void PrivateDecoderCrystalHD::RetrieveFrames(void)
{
- usleep(1000);
INIT_ST
- BC_DTS_STATUS status;
- st = DtsGetDriverStatus(m_device, &status);
- CHECK_ST
+ bool valid = false;
+ while (!m_kill_retrieval)
+ {
+ usleep(1000);
+ if (m_pause_retrieval)
+ continue;
- if (!status.ReadyListCount)
- return;
+ BC_DTS_STATUS status;
+ st = DtsGetDriverStatus(m_device, &status);
+ CHECK_ST
- BC_DTS_PROC_OUT out;
- memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
- st = DtsProcOutputNoCopy(m_device, 1, &out);
- if (BC_STS_FMT_CHANGE == st)
- {
- VERBOSE(VB_IMPORTANT, LOC + "Decoder reported format change.");
- CheckProcOutput(&out);
- return;
- }
- CHECK_ST
+ if (!status.ReadyListCount)
+ continue;
- if (!ok)
- {
- VERBOSE(VB_IMPORTANT, ERR + "Failed to retrieve decoded frame");
- return;
+ BC_DTS_PROC_OUT out;
+ memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
+ st = DtsProcOutputNoCopy(m_device, valid ? 2000 : 20, &out);
+
+ if (BC_STS_FMT_CHANGE == st)
+ {
+ VERBOSE(VB_IMPORTANT, LOC + "Decoder reported format change.");
+ CheckProcOutput(&out);
+ valid = true;
+ continue;
+ }
+ CHECK_ST
+
+ if (!ok)
+ {
+ VERBOSE(VB_IMPORTANT, ERR + "Failed to retrieve decoded frame");
+ continue;
+ }
+
+ //if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID)&& out.PicInfo.timeStamp)
+ //if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID))
+ if (ok && valid)
+ FillFrame(&out);
+ st = DtsReleaseOutputBuffs(m_device, NULL, false);
+ CHECK_ST
}
+}
- FillFrame(&out);
- st = DtsReleaseOutputBuffs(m_device, NULL, false);
- CHECK_ST
- RetrieveFrame();
+bool PrivateDecoderCrystalHD::StartRetrievalThread(void)
+{
+ m_pause_retrieval = false;
+ if (m_retrieval_thread)
+ return true;
+
+ m_retrieval_thread = new RetrievalThread(this);
+ if (!m_retrieval_thread)
+ return false;
+
+ m_retrieval_thread->start();
+ return true;
}
+
void PrivateDecoderCrystalHD::FillFrame(BC_DTS_PROC_OUT *out)
{
bool second_field = false;
@@ -541,6 +703,7 @@
void PrivateDecoderCrystalHD::AddFrameToQueue(void)
{
int i = 0;
+ m_decoded_frames_lock.lock();
// TODO is the following code needed
#if 0
bool found = false;
@@ -555,7 +718,12 @@
if (!found)
i = m_decoded_frames.size();
#endif
- m_decoded_frames.insert(i, m_frame);
+ m_decoded_frames.insert(0, m_frame);
+ VERBOSE(VB_PLAYBACK, LOC + QString("Decoded frame queue size %1")
+ .arg(m_decoded_frames.size()));
+ VERBOSE(VB_PLAYBACK, LOC + QString("Inserting frame with timecode %1")
+ .arg(m_frame->timecode));
+ m_decoded_frames_lock.unlock();
m_frame = NULL;
}
Index: libs/libmythtv/privatedecoder.h
===================================================================
--- libs/libmythtv/privatedecoder.h (revision 26445)
+++ libs/libmythtv/privatedecoder.h (working copy)
@@ -17,6 +17,8 @@
static PrivateDecoder* Create(const QString &decoder,
bool no_hardware_decode,
AVCodecContext *avctx);
+ virtual bool HasBufferedFrames(void) { return false; }
+ virtual int GetBufferedFrame(AVStream *stream, AVFrame *picture) { return 0; }
PrivateDecoder() { }
virtual ~PrivateDecoder() { }
virtual QString GetName(void) = 0;
Index: libs/libmythtv/avformatdecoder.h
===================================================================
--- libs/libmythtv/avformatdecoder.h (revision 26445)
+++ libs/libmythtv/avformatdecoder.h (working copy)
@@ -203,6 +203,7 @@
bool H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
bool PreProcessVideoPacket(AVStream *stream, AVPacket *pkt);
bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt);
+ bool ProcessVideoFrame(AVStream *stream, AVFrame *frame);
bool ProcessAudioPacket(AVStream *stream, AVPacket *pkt,
DecodeType decodetype);
bool ProcessSubtitlePacket(AVStream *stream, AVPacket *pkt);
Index: libs/libmyth/audiooutputalsa.cpp
===================================================================
--- libs/libmyth/audiooutputalsa.cpp (revision 26420)
+++ libs/libmyth/audiooutputalsa.cpp (working copy)
@@ -431,7 +431,9 @@
while (frames > 0)
{
+ VERBOSE(VB_AUDIO, QString("pcm_write_func -- start"));
lw = pcm_write_func(pcm_handle, tmpbuf, frames);
+ VERBOSE(VB_AUDIO, QString("pcm_write_func -- end"));
if (lw >= 0)
{
Index: libs/libmyth/audiooutputbase.cpp
===================================================================
--- libs/libmyth/audiooutputbase.cpp (revision 26420)
+++ libs/libmyth/audiooutputbase.cpp (working copy)
@@ -21,6 +21,7 @@
#define LOC QString("AO: ")
#define LOC_ERR QString("AO, ERROR: ")
+#define AUDIOTSTESTING 1
#define WPOS audiobuffer + org_waud
#define RPOS audiobuffer + raud
#define ABUF audiobuffer
@@ -1259,7 +1260,9 @@
// only send zeros if card doesn't already have at least one
// fragment of zeros -dag
+ VBAUDIOTS("WriteAudio Zeros Start");
WriteAudio(zeros, fragment_size);
+ VBAUDIOTS("WriteAudio Zeros Done");
continue;
}
else