Example #1
0
func parseRequest(w http.ResponseWriter, r *http.Request) (runMode string, s generator.Stream, err error) {
	urlBase := strings.Split(r.URL.Path, ".")[0]
	pathComps := strings.Split(urlBase, "/")
	runMode = "load"
	identifier := urlBase

	if len(pathComps) > 1 {
		runMode = pathComps[0]
		identifier = pathComps[1]
	}

	if runMode == "function" {
		functionId := identifier
		instructionString := functionId + "?" + r.URL.RawQuery
		si := generator.InstructionFromString(instructionString)
		s = generator.NewStream("temporary-stream", si)
		err = nil
	} else {
		s, err = generator.LoadStream(identifier)
		if err != nil && r.Method == "GET" {
			w.WriteHeader(404)
			w.Header().Add("Content-Type", "text/plain")
			fmt.Fprintln(w, "stream not found")
		}
	}

	w.Header().Add("Content-Type", "application/x-mpegurl")
	return
}
Example #2
0
func GenerateStreamJob(msg *workers.Msg) {
	jobStartTime := time.Now().Unix()
	jobStartTimeString := strconv.FormatInt(jobStartTime, 10)
	identifier, iderr := msg.Args().Get("identifier").String()
	if identifier == "" || iderr != nil {
		log.Println("No identifier! aborting!")
		return
	}

	client := datastore.RedisClient()
	lockid := "guide-stream-lock-" + identifier
	gotLock, err := client.SetNX(lockid, jobStartTimeString, 3*time.Second).Result()
	if !gotLock || err != nil {
		return
	}

	ticker := time.NewTicker(1 * time.Second)
	cancelChan := make(chan bool, 3)
	go func() {
		for {
			select {
			case <-ticker.C:
				client.Set(lockid, jobStartTimeString, 3*time.Second)
			case <-cancelChan:
				ticker.Stop()
				client.Del(lockid)
				return
			}
		}
	}()
	defer func() {
		cancelChan <- true
	}()

	stream, err := generator.LoadStream(identifier)
	if err != nil {
		log.Println("could not load given identifier", identifier, "aborting!")
		return
	}

	freebies := 0
	if stream.Playlist.Count() == 0 {
		freebies = 3
	}

	out := stream.Generate()
	for command := range out {
		if command.Type == "broadcast-segment" {
			durationMs := time.Duration(command.Segment.TargetDuration * 1000000)
			if freebies > 0 {
				durationMs = 0
				freebies = freebies - 1
			}
			canAdvance := time.After(durationMs * time.Microsecond)
			stream.ToChannel().SavePlaylist()
			<-canAdvance
		}
	}
	cancelChan <- true

	workers.Enqueue("guide-generate-stream-job", "GenerateStreamJob", map[string]string{
		"identifier": identifier,
	})
}