2023-03-27:avio_list_dir.c 是 FFmpeg 库自带的一个示例程序,它提供了列出目录中所有文件和子目录

2023-06-08 15:21:18 浏览数 (2)

2023-03-27:avio_list_dir.c 是 FFmpeg 库自带的一个示例程序,它提供了列出目录中所有文件和子目录的功能,请用go语言改写。

答案2023-03-27:

这段代码实现了通过 AVIOContext 列出指定目录下的文件和子目录,并打印出它们的名称、大小、类型、权限等信息。

具体流程如下:

1.设置 FFmpeg 库的路径,以及调用 AvformatNetworkInit() 初始化网络相关的组件。

2.调用 AvioOpenDir() 打开指定目录,获取 AVIODirContext 对象。

3.循环调用 AVIODirContext.AvioReadDir() 方法读取目录下的文件和子目录,每次读取到一个目录项后,输出该目录项的信息。如果已经读取完所有目录项,则退出循环。

4.输出格式化的目录项信息,包括类型、大小、名称、权限等。

5.在每次循环中需要调用 AVIODirContext.AvioFreeDirectoryEntry() 方法释放当前目录项所占用的内存空间。

6.最后调用 AvioCloseDir() 关闭目录并销毁 AVIODirContext 对象,调用 AvformatNetworkDeinit() 释放网络相关的资源。

需要注意的是,这段代码只能在支持 AVIOContext 的平台上运行,例如 Linux 上的文件系统或者 S3、HDFS 等云存储服务。而 Windows 平台上不支持 AVIOContext,因此无法使用该方法列出目录下的文件和子目录。

代码见github/moonfdd/ffmpeg-go。

执行命令:

代码语言:javascript复制
go run ./examples/internalexamples/avio_list_dir/main.go .

golang代码如下:

代码语言:javascript复制
package main

import (
  "fmt"
  "os"

  "github.com/moonfdd/ffmpeg-go/ffcommon"
  "github.com/moonfdd/ffmpeg-go/libavformat"
  "github.com/moonfdd/ffmpeg-go/libavutil"
)

func main() {

  os.Setenv("Path", os.Getenv("Path") ";./lib")
  ffcommon.SetAvutilPath("./lib/avutil-56.dll")
  ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")
  ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")
  ffcommon.SetAvfilterPath("./lib/avfilter-56.dll")
  ffcommon.SetAvformatPath("./lib/avformat-58.dll")
  ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")
  ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")
  ffcommon.SetAvswscalePath("./lib/swscale-5.dll")

  genDir := "./out"
  _, err := os.Stat(genDir)
  if err != nil {
    if os.IsNotExist(err) {
      os.Mkdir(genDir, 0777) //  Everyone can read write and execute
    }
  }
  main0()
}
func main0() (ret ffcommon.FInt) {

  libavutil.AvLogSetLevel(libavutil.AV_LOG_DEBUG)

  if len(os.Args) < 2 {
    usage(os.Args[0])
    ret = 1
    return
  }

  libavformat.AvformatNetworkInit()

  ret = list_op(os.Args[1])

  libavformat.AvformatNetworkDeinit()

  if ret < 0 {
    ret = 1
  }
  return
}

func type_string(type0 int32) string {
  switch type0 {
  case libavformat.AVIO_ENTRY_DIRECTORY:
    return "<DIR>"
  case libavformat.AVIO_ENTRY_FILE:
    return "<FILE>"
  case libavformat.AVIO_ENTRY_BLOCK_DEVICE:
    return "<BLOCK DEVICE>"
  case libavformat.AVIO_ENTRY_CHARACTER_DEVICE:
    return "<CHARACTER DEVICE>"
  case libavformat.AVIO_ENTRY_NAMED_PIPE:
    return "<PIPE>"
  case libavformat.AVIO_ENTRY_SYMBOLIC_LINK:
    return "<LINK>"
  case libavformat.AVIO_ENTRY_SOCKET:
    return "<SOCKET>"
  case libavformat.AVIO_ENTRY_SERVER:
    return "<SERVER>"
  case libavformat.AVIO_ENTRY_SHARE:
    return "<SHARE>"
  case libavformat.AVIO_ENTRY_WORKGROUP:
    return "<WORKGROUP>"
  case libavformat.AVIO_ENTRY_UNKNOWN:
  default:
    break
  }
  return "<UNKNOWN>"
}

func list_op(input_dir string) (ret int32) {
  var entry *libavformat.AVIODirEntry
  var ctx *libavformat.AVIODirContext
  var cnt int32
  var filemode [4]byte
  var uid_and_gid [20]byte

  //注意Windows下会返回-40,也就是Function not implement,方法未实现,也就是说windows下不支持此方法
  ret = libavformat.AvioOpenDir(&ctx, input_dir, nil)
  defer libavformat.AvioCloseDir(&ctx)

  if ret < 0 {
    libavutil.AvLog(uintptr(0), libavutil.AV_LOG_ERROR, "Cannot open directory: %s.n", libavutil.AvErr2str(ret))
    return
  }

  cnt = 0
  for {
    ret = ctx.AvioReadDir(&entry)
    if ret < 0 {
      libavutil.AvLog(uintptr(0), libavutil.AV_LOG_ERROR, "Cannot list directory: %s.n", libavutil.AvErr2str(ret))
      return
    }
    if entry == nil {
      break
    }
    if entry.Filemode == -1 {
      filemode[0] = '?'
      filemode[1] = '?'
      filemode[2] = '?'
    } else {
      f := fmt.Sprint(entry.Filemode)
      if len(f) >= 1 {
        filemode[0] = f[0]
      }
      if len(f) >= 2 {
        filemode[1] = f[1]
      }
      if len(f) >= 3 {
        filemode[2] = f[2]
      }
    }
    u := fmt.Sprintf("%d%d", entry.UserId, entry.GroupId)
    copy(uid_and_gid[0:19], []byte(u))

    if cnt == 0 {
      libavutil.AvLog(uintptr(0), libavutil.AV_LOG_INFO, "%-9s s 0s s %s s s sn",
        "TYPE", "SIZE", "NAME", "UID(GID)", "UGO", "MODIFIED",
        "ACCESSED", "STATUS_CHANGED")
    }
    libavutil.AvLog(uintptr(0), libavutil.AV_LOG_INFO, "%-9s s 0s s %s s s sn",
      type_string(entry.Type),
      fmt.Sprint(entry.Size),
      ffcommon.StringFromPtr(entry.Name),
      string(uid_and_gid[:]),
      fmt.Sprint(filemode),
      fmt.Sprint(entry.ModificationTimestamp),
      fmt.Sprint(entry.AccessTimestamp),
      fmt.Sprint(entry.StatusChangeTimestamp))
    libavformat.AvioFreeDirectoryEntry(&entry)
    cnt  
  }
  return
}

func usage(program_name string) {
  fmt.Printf("usage: %s input_dirnAPI example program to show how to list files in directory accessed through AVIOContext.n", program_name)
}

0 人点赞