Skip to content

Instantly share code, notes, and snippets.

@darren
Last active May 7, 2024 06:59
Show Gist options
  • Save darren/fe449a04bfddbed09ce477e1d33d6562 to your computer and use it in GitHub Desktop.
Save darren/fe449a04bfddbed09ce477e1d33d6562 to your computer and use it in GitHub Desktop.

Revisions

  1. darren revised this gist Feb 11, 2023. No changes.
  2. darren created this gist Feb 11, 2023.
    77 changes: 77 additions & 0 deletions rtp_http.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    package main

    import (
    "flag"
    "io"
    "log"
    "net"
    "net/http"
    "os"
    "strings"
    )

    var addr = flag.String("l", ":18000", "Listening address")
    var iface = flag.String("i", "eth0", "Listening multicast interface")

    var inf *net.Interface

    func handleHTTP(w http.ResponseWriter, req *http.Request) {
    parts := strings.FieldsFunc(req.URL.Path, func(r rune) bool {
    return r == '/'
    })

    if len(parts) < 2 {
    w.WriteHeader(http.StatusBadRequest)
    io.WriteString(w, "No address specified")
    return
    }

    raddr := parts[1]

    addr, err := net.ResolveUDPAddr("udp4", raddr)
    if err != nil {
    w.WriteHeader(http.StatusBadRequest)
    io.WriteString(w, err.Error())
    return
    }

    conn, err := net.ListenMulticastUDP("udp4", inf, addr)
    if err != nil {
    w.WriteHeader(http.StatusInternalServerError)
    io.WriteString(w, err.Error())
    return
    }
    defer conn.Close()

    w.Header().Set("Content-Type", "application/octet-stream")
    w.WriteHeader(http.StatusOK)
    n, err := io.Copy(w, conn)
    log.Printf("%s %s %d [%s]", req.RemoteAddr, req.URL.Path, n, req.UserAgent())
    }

    func main() {
    if os.Getppid() == 1 {
    log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime))
    } else {
    log.SetFlags(log.Lshortfile | log.LstdFlags)
    }

    flag.Parse()

    var err error
    inf, err = net.InterfaceByName(*iface)
    if err != nil {
    log.Fatal(err)
    return
    }

    var mux http.ServeMux
    mux.HandleFunc("/rtp/", handleHTTP)

    log.Fatal(http.ListenAndServe(*addr, &mux))
    }

    // 启动后使用用iina播放CCTV9: iina http://localhost:18000/rtp/239.3.1.62:8112
    //
    // 上面的实现vlc无法直接播放,需要解析rtp,提取出payload才能播放具体实现可以参考 retv的实现:
    // https://github.com/darren/retv/blob/54378d16d6e1042b9259280b3a7aea50087d0518/rtp.go#L73