Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,长修远,我们不能没有钱
随笔 - 172, 文章 - 0, 评论 - 257, 引用 - 0
数据加载中……

ffmpeg分析系列之六(再次探测输入的格式)

void *logctx= ap && ap->prealloced_context ? *ic_ptr : NULL; // 因为 ap == NULL, 所以 logctx 也 == NULL.
if (!fmt && (err = ff_probe_input_buffer(&pb, &fmt, filename, logctx, 0, logctx ? (*ic_ptr)->probesize : 0)) < 0) {
  goto fail;
}
// fmt == NULL 时才执行 ff_probe_input_buffer 函数, 因为 fmt 就等于NULL, 成立.


ff_probe_input_buffer函数的原型:
int ff_probe_input_buffer(ByteIOContext **pb, // 字节IO上下文, 执行url_fopen得到的
    AVInputFormat **fmt, // 输出参数: 输入的格式
    const char *filename, // 文件名
    void *logctx, // NULL
    unsigned int offset, // 0
    unsigned int max_probe_size) // 0


关键的代码片断:
/* 读待探测的数据 */
buf = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE);
if ((ret = get_buffer(*pb, buf + buf_offset, probe_size - buf_offset)) < 0) {
  /* fail if error was not end of file, otherwise, lower score */
  if (ret != AVERROR_EOF) {
    av_free(buf);
    return ret;
  }
  score = 0;
  ret = 0; /* error was end of file, nothing read */
}
pd.buf_size += ret;
pd.buf = &buf[offset];

memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE);

/* 猜测文件格式 */
*fmt = av_probe_input_format2(&pd, 1, &score);

get_buffer函数, 有两处比较关键:
int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
{

  /* 省略部分代码 */ /* 读包 */
  if(s->read_packet)
    len = s->read_packet(s->opaque, buf, size);


  /* 省略部分代码 */

  /* 填充缓冲 */

  fill_buffer(s);

  /* 省略部分代码 */

}





fill_buffer函数, 有一处比较关键:
static void fill_buffer(ByteIOContext *s)
{ /* 省略部分代码 */ /* 读包 */
  if(s->read_packet)
    len = s->read_packet(s->opaque, dst, len);

/* 省略部分代码 */
}





好了, 到第二次探测输入格式的地方了:
*fmt = av_probe_input_format2(&pd, 1, &score);


进入av_probe_input_format2函数:
AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
{
  AVInputFormat *fmt1, *fmt;
  int score;

  fmt = NULL;
  for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) {
    if (!is_opened == !(fmt1->flags & AVFMT_NOFILE))
      continue;

    /* 这次 is_opened == 1, fmt1->flags设置AVFMT_NOFILE标志才时成立 */

    /* 由于 h264_demuxer.flags == AVFMT_GENERIC_INDEX, 所以上面不成立, 继续执行 */ score = 0;
    if (fmt1->read_probe) {
      score = fmt1->read_probe(pd); /* 调用h264_demuxer.h264_probe */
    } else if (fmt1->extensions) {
      if (av_match_ext(pd->filename, fmt1->extensions)) { /* 文件名和格式扩展名的匹配 */

        /* h264_demuxer.extensions = "h26l,h264,264" */ score = 50;
      }
    }
 if (score > *score_max) {
    *score_max = score;
    fmt = fmt1;
  }else if (score == *score_max)
    fmt = NULL;
  }
  return fmt;
}

av_match_ext函数:
int av_match_ext(const char *filename, const char *extensions)
{
  const char *ext, *p;
  char ext1[32], *q;

  if(!filename)
    return 0;

  ext = strrchr(filename, '.');
  if (ext) {
    ext++;
    p = extensions;
    for(;;) {
      q = ext1;
      while (*p != '' && *p != ',' && q-ext1<sizeof(ext1)-1)
        *q++ = *p++;
      *q = '';
      if (!strcasecmp(ext1, ext))
        return 1;
      if (*p == '')
        break;
      p++;
    }
  }
  return 0;
}




@import url(http://www.cppblog.com/cutesoft_client/cuteeditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

posted on 2012-12-14 01:44 Khan 阅读(1695) 评论(0)  编辑 收藏 引用 所属分类: GCC/G++跨平台开发


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理