Comcast / mamba

Mamba is a Swift iOS, tvOS and macOS framework to parse, validate and write HTTP Live Streaming (HLS) data.
Apache License 2.0
180 stars 40 forks source link

Using .transform and replacing a tag of tagDescription PantosTag.Location results in a invalid playlist with literal #Location #73

Closed bes closed 5 years ago

bes commented 5 years ago

I am trying to rewrite a playlist, specifically change the Location

                let parser = PlaylistParser()
                let result = parser.parse(playlistData: data, url: url)
                switch result {
                case .parsedMaster(var master):
                    do {
                        try master.transform {
                            (tag: PlaylistTag) -> PlaylistTag in
                            var mutableTag = tag
                            case PantosTag.Location:
                                mutableTag = PlaylistTag(
                                    tagDescriptor: PantosTag.Location,
                                    stringTagData: /* some URL String */,
                                    parsedValues: nil
                                )
[... other stuff]

But when I do this i get something like this as output

#Location:http://MY-URL

When I compare the incoming tag and my mutableTag, I can see some differences that don't seem to be exposed by the API.

For example, tagName is nil in the incoming tag, but it's not possible to set it to nil using the exposed API AFAICT.

The reason I am creating a new tag is because tagData is immutable.

Expected Behavior

To be able to set a PantosTag.Location while doing .transform. A PlaylistTag with PantosTag.Location should be written as the string in tagData, without any decoration.

Observed Behavior

It's not possible to set a correct PantosTag.Location during .transform. The PlaylistTag is decorated with #Location:... when writing it.

Reproduction Steps

  1. Parse any playlist with LocationTags
  2. Try to replace any LocationTag with a new LocationTag
  3. write the playlist
  4. Observe literal #Location rows, which are not valid HLS.

Observed on device(s):

Observed on OS Version(s):


Thanks for all the good work! I hope I am just doing something silly and this can/should be done in a completely different way.

bes commented 5 years ago

One way to solve my issue is to patch PlaylistTag.swift like so:

    public init(tagDescriptor: PlaylistTagDescriptor,
                tagData: MambaStringRef,
-               tagName: MambaStringRef,
+               tagName: MambaStringRef?,
                parsedValues: PlaylistTagDictionary? = nil,
                duration: CMTime = CMTime.invalid) {

        self.tagDescriptor = tagDescriptor
        self.tagData = tagData
        self.parsedValues = parsedValues
        self.tagName = tagName
        self.duration = duration
    }

But there might be a better way to solve it generically.

bes commented 5 years ago

If I wasn't so bad at reading I would have noticed this initializer

    /**
     Initializer for creating `PlaylistTag`s while parsing HLS. Specialized for tags that do not have tag
     names (i.e. PantosTag.Comment and PantosTag.Location)

     - parameter tagDescriptor: An PlaylistTagDescriptor.

     - parameter tagData: The tag data as a `MambaStringRef`.
     */
    public init(tagDescriptor: PlaylistTagDescriptor,
                tagData: MambaStringRef) {

        self.tagDescriptor = tagDescriptor
        self.tagData = tagData
        self.tagName = nil
        self.duration = CMTime.invalid
    }

Which is obviously everything I need facepalm

dcoufal commented 5 years ago

Yeah, constructing tags is a little difficult for the special case tags. Glad you figured it out.