mirror of https://github.com/FFmpeg/FFmpeg.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
3.7 KiB
158 lines
3.7 KiB
/* |
|
* .Y.U.V image format |
|
* Copyright (c) 2003 Fabrice Bellard. |
|
* |
|
* This library is free software; you can redistribute it and/or |
|
* modify it under the terms of the GNU Lesser General Public |
|
* License as published by the Free Software Foundation; either |
|
* version 2 of the License, or (at your option) any later version. |
|
* |
|
* This library is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
* Lesser General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU Lesser General Public |
|
* License along with this library; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
#include "avformat.h" |
|
|
|
static int sizes[][2] = { |
|
{ 640, 480 }, |
|
{ 720, 480 }, |
|
{ 720, 576 }, |
|
{ 352, 288 }, |
|
{ 352, 240 }, |
|
{ 160, 128 }, |
|
{ 512, 384 }, |
|
{ 640, 352 }, |
|
{ 640, 240 }, |
|
}; |
|
|
|
static int infer_size(int *width_ptr, int *height_ptr, int size) |
|
{ |
|
int i; |
|
|
|
for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) { |
|
if ((sizes[i][0] * sizes[i][1]) == size) { |
|
*width_ptr = sizes[i][0]; |
|
*height_ptr = sizes[i][1]; |
|
return 0; |
|
} |
|
} |
|
return -1; |
|
} |
|
|
|
static int yuv_read(ByteIOContext *f, |
|
int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque) |
|
{ |
|
ByteIOContext pb1, *pb = &pb1; |
|
int img_size, ret; |
|
char fname[1024], *p; |
|
int size; |
|
URLContext *h; |
|
AVImageInfo info1, *info = &info1; |
|
|
|
/* XXX: hack hack */ |
|
h = url_fileno(f); |
|
img_size = url_seek(h, 0, SEEK_END); |
|
url_get_filename(h, fname, sizeof(fname)); |
|
|
|
if (infer_size(&info->width, &info->height, img_size) < 0) { |
|
return -EIO; |
|
} |
|
info->pix_fmt = PIX_FMT_YUV420P; |
|
|
|
ret = alloc_cb(opaque, info); |
|
if (ret) |
|
return ret; |
|
|
|
size = info->width * info->height; |
|
|
|
p = strrchr(fname, '.'); |
|
if (!p || p[1] != 'Y') |
|
return -EIO; |
|
|
|
get_buffer(f, info->pict.data[0], size); |
|
|
|
p[1] = 'U'; |
|
if (url_fopen(pb, fname, URL_RDONLY) < 0) |
|
return -EIO; |
|
|
|
get_buffer(pb, info->pict.data[1], size / 4); |
|
url_fclose(pb); |
|
|
|
p[1] = 'V'; |
|
if (url_fopen(pb, fname, URL_RDONLY) < 0) |
|
return -EIO; |
|
|
|
get_buffer(pb, info->pict.data[2], size / 4); |
|
url_fclose(pb); |
|
return 0; |
|
} |
|
|
|
static int yuv_write(ByteIOContext *pb2, AVImageInfo *info) |
|
{ |
|
ByteIOContext pb1, *pb; |
|
char fname[1024], *p; |
|
int i, j, width, height; |
|
UINT8 *ptr; |
|
URLContext *h; |
|
static const char *ext = "YUV"; |
|
|
|
/* XXX: hack hack */ |
|
h = url_fileno(pb2); |
|
url_get_filename(h, fname, sizeof(fname)); |
|
|
|
p = strrchr(fname, '.'); |
|
if (!p || p[1] != 'Y') |
|
return -EIO; |
|
|
|
width = info->width; |
|
height = info->height; |
|
|
|
for(i=0;i<3;i++) { |
|
if (i == 1) { |
|
width >>= 1; |
|
height >>= 1; |
|
} |
|
|
|
if (i >= 1) { |
|
pb = &pb1; |
|
p[1] = ext[i]; |
|
if (url_fopen(pb, fname, URL_WRONLY) < 0) |
|
return -EIO; |
|
} else { |
|
pb = pb2; |
|
} |
|
|
|
ptr = info->pict.data[i]; |
|
for(j=0;j<height;j++) { |
|
put_buffer(pb, ptr, width); |
|
ptr += info->pict.linesize[i]; |
|
} |
|
put_flush_packet(pb); |
|
if (i >= 1) { |
|
url_fclose(pb); |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
static int yuv_probe(AVProbeData *pd) |
|
{ |
|
if (match_ext(pd->filename, "Y")) |
|
return AVPROBE_SCORE_MAX; |
|
else |
|
return 0; |
|
} |
|
|
|
AVImageFormat yuv_image_format = { |
|
"yuv", |
|
"Y", |
|
yuv_probe, |
|
yuv_read, |
|
(1 << PIX_FMT_YUV420P), |
|
yuv_write, |
|
};
|
|
|