1 /*******************************************************************************
3 * This file is part of the Ogg Vorbis DirectShow filter collection *
5 * Copyright (c) 2001, Tobias Waldvogel *
6 * All rights reserved. *
8 * Redistribution and use in source and binary forms, with or without *
9 * modification, are permitted provided that the following conditions are met: *
11 * - Redistributions of source code must retain the above copyright notice, *
12 * this list of conditions and the following disclaimer. *
14 * - Redistributions in binary form must reproduce the above copyright notice, *
15 * this list of conditions and the following disclaimer in the documentation *
16 * and/or other materials provided with the distribution. *
18 * - The names of the contributors may not be used to endorse or promote *
19 * products derived from this software without specific prior written *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" *
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE *
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF *
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN *
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) *
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
32 * POSSIBILITY OF SUCH DAMAGE. *
34 *******************************************************************************/
36 // This class is used for queueing Ogg pages
38 #include "OggPageQueue.h"
40 COggPageQueue::COggPageQueue()
42 m_pPageListFirst
= NULL
;
43 m_pPageListTail
= NULL
;
44 m_pFreePageList
=NULL
;
45 m_iHeaderAlloc
= 0x80;
46 m_iBodyAlloc
= 0x1400;
50 COggPageQueue::~COggPageQueue()
55 void COggPageQueue::OggPageQueueClearFreeList()
57 // The lock must already be set
60 while (m_pFreePageList
)
62 pTemp
= m_pFreePageList
;
63 m_pFreePageList
= m_pFreePageList
->pNext
;
64 delete [] pTemp
->og
.header
;
65 delete [] pTemp
->og
.body
;
70 // Clears the page list and the free list
71 void COggPageQueue::OggPageQueueFlush()
73 CAutoLock
lock(&m_csPageList
);
77 // Clear the page list
78 while (m_pPageListFirst
)
80 pTemp
= m_pPageListFirst
;
81 m_pPageListFirst
= m_pPageListFirst
->pNext
;
82 delete [] pTemp
->og
.header
;
83 delete [] pTemp
->og
.body
;
86 m_pPageListTail
= NULL
;
89 OggPageQueueClearFreeList();
93 void COggPageQueue::OggPageEnqueue(ogg_page
* pog
, REFERENCE_TIME
* prtTime
)
95 tPageNode
* pNode
= NULL
;
96 CAutoLock
lock(&m_csPageList
);
98 if ((pog
->header_len
<= m_iHeaderAlloc
) &&
99 (pog
->body_len
<= m_iBodyAlloc
)) // => Page fits
101 if (m_pFreePageList
) // Are there pages in the free list ?
103 // reuse an existing page
104 pNode
= m_pFreePageList
;
105 m_pFreePageList
= m_pFreePageList
->pNext
;
110 // Page doesn't fit => we must increase the size
111 if (pog
->header_len
> m_iHeaderAlloc
)
112 m_iHeaderAlloc
= (pog
->header_len
& 0xffffff80) + 0x80;
113 if (pog
->body_len
> m_iBodyAlloc
)
114 m_iBodyAlloc
= (pog
->body_len
& 0xfffffc00) + 0x400;
115 OggPageQueueClearFreeList(); // Clear all existing free pages
118 if (!pNode
) // we must create a new one because free list was empty or it didnĀ“t fit
120 pNode
= new tPageNode
;
121 pNode
->header_size
= m_iHeaderAlloc
;
122 pNode
->og
.header
= new unsigned char[m_iHeaderAlloc
];
123 pNode
->body_size
= m_iBodyAlloc
;
124 pNode
->og
.body
= new unsigned char[m_iBodyAlloc
];
128 memcpy(pNode
->og
.header
, pog
->header
, pog
->header_len
);
129 pNode
->og
.header_len
= pog
->header_len
;
130 memcpy(pNode
->og
.body
, pog
->body
, pog
->body_len
);
131 pNode
->og
.body_len
= pog
->body_len
;
132 pNode
->rtPos
= prtTime
? *prtTime
: 0;
134 // and add this page at the end of the list
138 m_pPageListTail
->pNext
= pNode
; // Add it as last one
139 m_pPageListTail
= m_pPageListTail
->pNext
; // and let tail point to it
143 m_pPageListFirst
= pNode
;
144 m_pPageListTail
= pNode
;
150 // Get a page from the queue
151 tPageNode
* COggPageQueue::OggPageDequeue()
153 CAutoLock
lock(&m_csPageList
);
156 if (!m_pPageListFirst
) return NULL
;
158 pPage
= m_pPageListFirst
;
159 m_pPageListFirst
= m_pPageListFirst
->pNext
;
160 if (m_pPageListFirst
== NULL
)
161 m_pPageListTail
= NULL
;
167 void COggPageQueue::OggPageRelease(tPageNode
* pNode
)
169 if ((pNode
->header_size
< m_iHeaderAlloc
) ||
170 (pNode
->body_size
< m_iBodyAlloc
))
172 // This node can not be use anymore because the size has been increased
173 delete [] pNode
->og
.header
;
174 delete [] pNode
->og
.body
;
179 // Otherwise add it to the free list
180 CAutoLock
lock(&m_csPageList
);
182 pNode
->pNext
= m_pFreePageList
;
183 m_pFreePageList
= pNode
;
186 // return the number of pages in the queue
187 int COggPageQueue::OggPageQueuePages()
189 CAutoLock
lock(&m_csPageList
);
190 return m_iPagesInQueue
;
193 // checks if the queue is empty
194 bool COggPageQueue::OggPageQueuePageReady()
196 CAutoLock
lock(&m_csPageList
);
197 return m_pPageListFirst
!= NULL
;
200 // returns the time of the first available page
201 bool COggPageQueue::OggPageQueueCurrTime(REFERENCE_TIME
* rtTime
)
203 CAutoLock
lock(&m_csPageList
);
205 if (!m_pPageListFirst
)
208 *rtTime
= m_pPageListFirst
->rtPos
;