为了方便播放器直接播放,也为实现所谓智能识别文件分辨率和格式,对文件名称进行解析,代码如下:
1 | #define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) |
// 从文件名称解析分辨率及YUV格式
void find_resolution(char* filename, int& fmt_idx, int& width, int& height)
{
#define str_debug
int i = 0;
int j = 0;
int len = 0;
int pos = 0;
char* tmp = NULL;
char* p = NULL;
char c_width[8] = {0};
char c_height[8] = {0};
char c_fmt[8] = {0};
char c_res[8] = {0};
char c_file[128] = {0};
const char* fmt_str[] = {
"yuv420",
"yv12",
"yuv422",
"yv16",
"yuv444",
"yuyv",
"yvyu",
"uyvy",
"vyuy",
"nv12",
"nv21",
"nv16",
"nv61",
"yuv420sp",
"yuv422sp",
};
const char* res_str[] = {
"cif",
"qcif",
"480p",
"720p",
"1080p",
};
const char* wh_str[] = {
"352x288",
"176x144",
"720x480",
"1280x720",
"1920x1080",
};
int idx = -1;
fmt_idx = -2; // trick...
#if 0
len = strlen(filename);
str_debug(“org string len:%d %s\b”, len, filename);
#endif
// 查找后缀名
tmp = strrchr(filename, '.');
if (tmp != NULL)
{
strncpy(c_file, filename, tmp-filename);
pos = strlen(tmp+1);
//str_debug("find ext: %s(%d) %s %s %d\n", tmp+1, pos, filename, c_file, tmp-filename);
// 查找格式字符串
for (i = 0; i < ARRAY_ELEMS(fmt_str); i++)
{
p = strstr(tmp+1, fmt_str[i]);
if (p != NULL)
{
strncpy(c_fmt, p, strlen(fmt_str[i]));
idx = i;
}
}
}
else
{
strcpy(c_file, filename);
}
str_debug("second string:%s \n", c_file);
if (idx == 0 && pos != 1) idx = -1;
if (idx == 13) idx = 9;
if (idx == 14) idx = 11;
// 这里打印的是最大匹配的
if (idx != -1)
str_debug("fmt(externsion)[%d]: %s(=%s)\n", idx, c_fmt, fmt_str[idx]);
// 查找格式字符串
for (i = 0; i < ARRAY_ELEMS(fmt_str); i++)
{
p = strstr(c_file, fmt_str[i]);
//str_debug("p: %s\n", p);
if (p != NULL)
{
strncpy(c_fmt, p, strlen(fmt_str[i]));
fmt_idx = i;
}
}
if (fmt_idx == 13) fmt_idx = 9;
if (fmt_idx == 14) fmt_idx = 11;
// 这里打印的是最大匹配的
if (fmt_idx != -1)
str_debug("fmt[%d]: %s(=%s)\n", fmt_idx, c_fmt, fmt_str[fmt_idx]);
if (idx != -1 && fmt_idx == -1) fmt_idx = idx;
if (fmt_idx != -1)
str_debug("---final fmt[%d]: %s(=%s)---\n", fmt_idx, c_fmt, fmt_str[fmt_idx]);
fmt_idx+=1;
// 查找分辨率字符串
for (i = 0; i < ARRAY_ELEMS(res_str); i++)
{
//str_debug("res--: %s\n", res_str[i]);
p = strstr(c_file, res_str[i]);
if (p != NULL)
{
strncpy(c_res, p, strlen(res_str[i]));
idx = i;
//str_debug("res: %s\n", c_res);
}
}
if (idx != -1)
{
sscanf(wh_str[idx], "%dx%d", &width, &height);
str_debug("res[%d]: %s %d %d\n", idx, c_res, width, height);
}
//////////////////////
// 解析宽高
len = strlen(c_file);
pos = strcspn(c_file, "xX");
if (len == pos) // 没有找到直接返回
{
str_debug("---final width: %d height: %d---\n", width, height);
return;
}
tmp = c_file + pos;
str_debug("find1 x[%d len: %d] %s\n", pos, len, tmp);
//return;
p = c_file;
len = len - pos + 1;
j = pos;
// 找到'x'前面的数字
for (i = 0; i < len && j > 0; i++)
{
str_debug("pos: %d %c\n", j, p[j]);
if (!isdigit(p[--j]))
{
j++;
break;
}
}
str_debug("before x i:%d j: %d tmp: %s\n", i, j, p+j);
strncpy(c_width, p+j, i);
width = atoi(c_width);
str_debug("c_width: %s %d\n", c_width, width);
// 找到'x'后面的数字
p = c_file + pos+1; // 跳过'x'
len = p - c_file;
str_debug("after find x[%d] %s\n", pos, p);
for (i = 0; i < len; i++)
{
if (!isdigit(p[i]))
break;
}
strncpy(c_height, p, i);
height = atoi(c_height);
str_debug("c_height: %s %d\n", c_height, height);
if (idx == -1 && (width == 0 || height == 0))
width = height = -1;
if (idx != -1 && (width == 0 || height == 0))
sscanf(wh_str[idx], "%dx%d", &width, &height);
str_debug("---final width: %d height: %d---\n", width, height);
str_debug("\n");
}
```
YUV格式排列是根据界面上YUV格式的顺序,当找到一个格式时,则返回其索引时,直接使用即可。至于宽高,则使用strcspn函数来查找“x”前后的数字。一个简单功能代码,占用差不多200行代码,一来是技术问题,二来有很多逻辑处理,如YUV格式,可以在文件名给出,也可以通过后缀名给出,分辨率可以直接用qcif、1080p这类的熟知的方法,也可以使用176x144这类的方式,另外还有处理同时存在不同的格式的优化级。当然,按正常使用情况下,这个函数是可以正常工作的。
李迟 2015.8.16 周日 上午