root/branches/perian-1.0/ff_dataref.c

Revision 271, 5.7 kB (checked in by dconrad, 2 years ago)

Support for AVSEEK_SIZE. Also, it seems it's best to return -1 if we don't support the seek mode. Fixes duration calcualtion for FLVs, which in turn fixes displaying the import progress.

Line 
1 /*****************************************************************************
2 *
3 *  Avi Import Component dataref interface for libavformat
4 *
5 *  Copyright(C) 2006 Christoph Naegeli <chn1@mac.com>
6 *
7 *  This library is free software; you can redistribute it and/or
8 *  modify it under the terms of the GNU Lesser General Public
9 *  License as published by the Free Software Foundation; either
10 *  version 2.1 of the License, or (at your option) any later version.
11
12 *  This library is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 *  Lesser General Public License for more details.
16
17 *  You should have received a copy of the GNU Lesser General Public
18 *  License along with this library; if not, write to the Free Software
19 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 *
21 ****************************************************************************/
22
23 #include "avformat.h"
24
25 #include <QuickTime/QuickTime.h>
26
27 struct _dataref_private {
28         Handle dataRef;
29         OSType dataRefType;
30         DataHandler dh;
31         int64_t pos;
32         int64_t size;
33         unsigned char supportsWideOffsets;
34 };
35 typedef struct _dataref_private dataref_private;
36
37 /* DataRef Wrapper for QuickTime */
38
39 /* !!! THIS FUNCTION ASSUMES h->priv_data IS VALID in contrary to the other open functions
40 * found in ffmpeg */
41 static int dataref_open(URLContext *h, const char *filename, int flags)
42 {
43         ComponentResult result;
44         dataref_private *private;
45         wide fsize;
46         long access = 0;
47        
48         if(flags & URL_RDWR) {
49                 access = kDataHCanRead | kDataHCanWrite;
50         } else if(flags & URL_WRONLY) {
51                 access = kDataHCanWrite;
52         } else {
53                 access = kDataHCanRead;
54         }
55        
56         private = h->priv_data;
57         result = OpenAComponent(GetDataHandler(private->dataRef, private->dataRefType, access), &private->dh);
58         require_noerr(result,bail);
59        
60         result = DataHSetDataRef(private->dh, private->dataRef);
61         require_noerr(result,bail);
62        
63         if(access & kDataHCanRead) {
64                 result = DataHOpenForRead(private->dh);
65                 require_noerr(result,bail);
66         }
67         if(access & kDataHCanWrite) {
68                 result = DataHOpenForWrite(private->dh);
69                 require_noerr(result,bail);
70         }
71        
72         private->pos = 0ll;
73         private->size = 0ll;
74        
75         result = DataHGetFileSize64(private->dh, &fsize);
76         if(result == noErr) {
77                 private->size = (int64_t)fsize.lo;
78                 private->size += (int64_t)fsize.hi << 32;
79                 // Our data handler supports wide offsets. Remember for later use.
80                 private->supportsWideOffsets = 1;
81         } else {
82                 long size32;
83                 result = DataHGetFileSize(private->dh, &size32);
84                 require_noerr(result, bail);
85                 private->size = size32;
86         }
87        
88 bail:
89                 return result;
90 } /* dataref_open() */
91
92 static int dataref_read(URLContext *h, unsigned char *buf, int size)
93 {
94         int result;
95         int64_t read;
96
97         dataref_private *p = (dataref_private*)h->priv_data;
98        
99         read = p->size - p->pos;
100         read = (read < size) ? read : size;
101        
102         if(p->supportsWideOffsets) {
103                 wide offset;
104                 offset.hi = p->pos >> 32;
105                 offset.lo = (UInt32)p->pos;
106                
107                 result = DataHScheduleData64(p->dh, (Ptr)buf, &offset, (long)read, 0, NULL, NULL);
108         } else {
109                 result = DataHScheduleData(p->dh, (Ptr)buf, (long)p->pos, (long)read, 0, NULL, NULL);
110         }
111        
112         if(result != noErr) {
113                 read = -1;
114                 goto bail;
115         }
116        
117         p->pos += read;
118        
119 bail:
120                 return (int)read;
121 } /* dataref_read() */
122
123 static int dataref_write(URLContext *h, unsigned char *buf, int size)
124 {
125         int result;
126         int written = size;
127         dataref_private *p = (dataref_private*)h->priv_data;
128        
129         if(p->supportsWideOffsets) {
130                 wide offset;
131                 offset.hi = p->pos >> 32;
132                 offset.lo = (UInt32)p->pos;
133                
134                 result = DataHWrite64(p->dh, (Ptr)buf, &offset, size, NULL, 0);
135         } else {
136                 result = DataHWrite(p->dh, (Ptr)buf, (long)p->pos, size, NULL, 0);
137         }
138        
139         if(result != noErr) {
140                 written = -1;
141                 goto bail;
142         }
143        
144         p->pos += written;
145        
146 bail:
147                 return written;
148 } /* dataref_write() */
149
150 static offset_t dataref_seek(URLContext *h, offset_t pos, int whence)
151 {
152         dataref_private *p = (dataref_private*)h->priv_data;
153        
154         switch(whence) {
155                 case SEEK_SET:
156                         p->pos = pos;
157                         break;
158                 case SEEK_CUR:
159                         p->pos += pos;
160                         break;
161                 case SEEK_END:
162                         p->pos = p->size + pos;
163                         break;
164                 case AVSEEK_SIZE:
165                         return p->size;
166                 default:
167                         return -1;
168         }
169        
170         return p->pos;
171 } /* dataref_seek() */
172
173 static int dataref_close(URLContext *h)
174 {
175         dataref_private *p = (dataref_private*)h->priv_data;
176        
177         CloseComponent(p->dh);
178         p->dh = 0;
179         p->pos = 0;
180         p->size = 0;
181        
182         av_free(p);
183         h->priv_data = NULL;
184        
185         return 0;
186 } /* dataref_close() */
187
188 URLProtocol dataref_protocol = {
189     "Data Ref",
190     dataref_open,
191     dataref_read,
192     dataref_write,
193     dataref_seek,
194     dataref_close,
195 };
196
197 /* This is the public function to open bytecontext withs datarefs */
198 OSStatus url_open_dataref(ByteIOContext *pb, Handle dataRef, OSType dataRefType, DataHandler *dataHandler, Boolean *wideSupport, int64_t *dataSize)
199 {
200         URLContext *uc;
201         URLProtocol *up;
202         OSStatus err;
203         dataref_private *private;
204        
205         private = av_mallocz(sizeof(dataref_private));
206         private->dataRef = dataRef;
207         private->dataRefType = dataRefType;
208        
209         up = &dataref_protocol;
210        
211         uc = av_mallocz(sizeof(URLContext));
212         if(!uc) {
213                 err = -ENOMEM;
214                 return err;
215         }
216         uc->filename[0] = '\0';
217         uc->prot = up;
218         uc->flags = URL_RDONLY; // we're just using the read access...
219         uc->is_streamed = 0; // not streamed...
220         uc->max_packet_size = 0; // stream file
221         uc->priv_data = private;
222        
223         err = up->url_open(uc, uc->filename, URL_RDONLY);
224                
225         if(err < 0) {
226                 av_free(uc);
227                 return err;
228         }
229         err = url_fdopen(pb, uc);
230         if(err < 0) {
231                 url_close(uc);
232                 return err;
233         }
234        
235         if(dataHandler)
236                 *dataHandler = private->dh;
237        
238         if(wideSupport)
239                 *wideSupport = private->supportsWideOffsets;
240        
241         if(dataSize)
242                 *dataSize = private->size;     
243        
244         return noErr;
245 } /* url_open_dataref() */
Note: See TracBrowser for help on using the browser.