Skip to content

Commit

Permalink
Merge pull request #6811 from ant-media/update-ffmpeg
Browse files Browse the repository at this point in the history
Update FFmpeg to 7.1
  • Loading branch information
mekya authored Nov 20, 2024
2 parents 06ae1d9 + 309edb9 commit d8abd5c
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 254 deletions.
6 changes: 5 additions & 1 deletion .github/actions/build-projects/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,8 @@ runs:
cp -a ManagementConsole_AngularApp/node_modules/. ~/ManagementConsole_AngularApp-node_modules-cache/

- name: Replace ffmpeg builds
shell: bash
run: |
wget -O ~/.m2/repository/org/bytedeco/ffmpeg/7.1-1.5.11/ffmpeg-7.1-1.5.11-linux-x86_64.jar https://storage.sbg.cloud.ovh.net/v1/AUTH_8cb28f9bc6ee43f0a3a1825efbb4311e/test-storage/ffmpeg-7.1-1.5.11-linux-x86_64.jar
wget -O ~/.m2/repository/org/bytedeco/ffmpeg/7.1-1.5.11/ffmpeg-7.1-1.5.11-linux-arm64.jar https://storage.sbg.cloud.ovh.net/v1/AUTH_8cb28f9bc6ee43f0a3a1825efbb4311e/test-storage/ffmpeg-7.1-1.5.11-linux-arm64.jar
12 changes: 0 additions & 12 deletions download_custom_ffmpeg_builds.sh

This file was deleted.

21 changes: 1 addition & 20 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -764,16 +764,7 @@
</arguments>
</configuration>
</execution>
<execution>
<id>download-custom-ffmpeg-builds</id> <!-- We're downloading custom builds because original files are updated when building and our custom build not works. We overwrite these info in assembely files -->
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>download_custom_ffmpeg_builds.sh</executable>
</configuration>
</execution>


</executions>
</plugin>
Expand Down Expand Up @@ -975,16 +966,6 @@
</arguments>
</configuration>
</execution>
<execution>
<id>download-custom-ffmpeg-builds</id> <!-- We're downloading custom builds because original files are updated when building and our custom build not works. We overwrite these info in assembely files -->
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>download_custom_ffmpeg_builds.sh</executable>
</configuration>
</execution>
</executions>

</plugin>
Expand Down
14 changes: 1 addition & 13 deletions src/main/assembly/server.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,10 @@
<exclude>cuda*.jar</exclude>


<!-- exclude these files becauwe we write below from the custom build -->

<exclude>ffmpeg*linux-x86_64.jar</exclude>
<exclude>ffmpeg*linux-arm64.jar</exclude>


</excludes>
</fileSet>
<fileSet> <!-- Overwrite Custom FFmepg Build Plugins - these files are downloaded autoomatically in pom.xml-->
<directory>${project.basedir}</directory>
<outputDirectory>plugins</outputDirectory>
<includes>
<include>ffmpeg-*.jar</include>
</includes>

</fileSet>

<fileSet>
<directory>${project.basedir}/src/main/server</directory>
<outputDirectory></outputDirectory>
Expand Down
11 changes: 1 addition & 10 deletions src/main/assembly/server_enterprise.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,9 @@
<exclude>cuda*macosx*.jar</exclude>
<exclude>cuda*windows*.jar</exclude>

<!-- exclude these files becauwe we write below from the custom build -->
<exclude>ffmpeg*linux-x86_64.jar</exclude>
<exclude>ffmpeg*linux-arm64.jar</exclude>

</excludes>
</fileSet>
<fileSet> <!-- Overwrite Custom FFmepg Build Plugins - these files are downloaded autoomatically in pom.xml -->
<directory>${project.basedir}</directory>
<outputDirectory>plugins</outputDirectory>
<includes>
<include>ffmpeg-*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/main/server</directory>
<outputDirectory></outputDirectory>
Expand Down
174 changes: 86 additions & 88 deletions src/main/java/io/antmedia/filter/HlsManifestModifierFilter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.antmedia.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
Expand All @@ -15,13 +14,11 @@
import jakarta.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.ws.rs.HttpMethod;

import org.springframework.util.StreamUtils;
import org.springframework.web.util.ContentCachingResponseWrapper;
import io.lindstrom.m3u8.model.MediaPlaylist;
import io.lindstrom.m3u8.model.MediaSegment;
Expand All @@ -42,64 +39,78 @@ public class HlsManifestModifierFilter extends AbstractFilter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest =(HttpServletRequest)request;
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;

String method = httpRequest.getMethod();
if (HttpMethod.GET.equals(method) && httpRequest.getRequestURI().endsWith("m3u8")) {
//only accept GET methods

//start date is in seconds since epoch
String startDate = request.getParameter(START);
//end date is in seconds since epoch
String endDate = request.getParameter(END);
String token = request.getParameter("token");
String subscriberId = request.getParameter("subscriberId");
String subscriberCode = request.getParameter("subscriberCode");

boolean parameterExists = !StringUtils.isNullOrEmpty(token) || !StringUtils.isNullOrEmpty(subscriberId) || !StringUtils.isNullOrEmpty(subscriberCode);

if(httpRequest.getRequestURI().contains(ADAPTIVE_SUFFIX) && parameterExists){
addSecurityParametersToAdaptiveM3u8File(token, subscriberId, subscriberCode, request, response, chain);
}

if(StringUtils.isNullOrEmpty(startDate) || StringUtils.isNullOrEmpty(endDate)) {
if (!httpRequest.getRequestURI().contains(ADAPTIVE_SUFFIX) && parameterExists) {
addSecurityParametersToSegmentUrls(token, subscriberId, subscriberCode, request, response, chain);
}
else {
chain.doFilter(httpRequest, response);
}
}
else {
long start = Long.parseLong(startDate);
long end = Long.parseLong(endDate);

ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response);
boolean parameterExists = !StringUtils.isNullOrEmpty(token) ||
!StringUtils.isNullOrEmpty(subscriberId) ||
!StringUtils.isNullOrEmpty(subscriberCode);



// Use ContentCachingResponseWrapper for modifications
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(httpResponse);

try
{
// Proceed with adaptive and regular m3u8 handling
if (httpRequest.getRequestURI().contains(ADAPTIVE_SUFFIX) && parameterExists)
{
addSecurityParametersToAdaptiveM3u8File(token, subscriberId, subscriberCode, request, responseWrapper, chain);
}
else if (StringUtils.isNullOrEmpty(startDate) || StringUtils.isNullOrEmpty(endDate))
{
if (!httpRequest.getRequestURI().contains(ADAPTIVE_SUFFIX) && parameterExists)
{
addSecurityParametersToSegmentUrls(token, subscriberId, subscriberCode, request, responseWrapper, chain);
}
else
{
chain.doFilter(request, responseWrapper);
}
}
else
{
// Handling of custom start/end time range for playlist segments

chain.doFilter(request, responseWrapper);
long start = Long.parseLong(startDate);
long end = Long.parseLong(endDate);
chain.doFilter(request, responseWrapper);

int status = responseWrapper.getStatus();
int status = responseWrapper.getStatus();
if (HttpServletResponse.SC_OK <= status && status <= HttpServletResponse.SC_BAD_REQUEST) {

if (HttpServletResponse.SC_OK <= status && status <= HttpServletResponse.SC_BAD_REQUEST)
{
try {
// Get the original response data
final byte[] originalData = responseWrapper.getContentAsByteArray();
String original = new String(originalData);
String original = new String(originalData, StandardCharsets.UTF_8);

MediaPlaylistParser parser = new MediaPlaylistParser();
MediaPlaylist playList = parser.readPlaylist(original);

List<MediaSegment> segments = new ArrayList<>();

for (MediaSegment segment : playList.mediaSegments()) {
segment.programDateTime().ifPresent(dateTime -> {
for (MediaSegment segment : playList.mediaSegments())
{
segment.programDateTime().ifPresent(dateTime ->
{
long time = dateTime.toEpochSecond();
if(time >= start && time <= end) {
if (time >= start && time <= end)
{
segments.add(MediaSegment.builder()
.duration(segment.duration())
.uri(segment.uri())
.build());
}
});

}

MediaPlaylist newPlayList = MediaPlaylist.builder()
Expand All @@ -109,89 +120,77 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
.addAllMediaSegments(segments)
.build();

// Modify the original data
MediaPlaylistParser parser2 = new MediaPlaylistParser();

String newData = parser2.writePlaylistAsString(newPlayList);

if(parameterExists) {
String newData = new MediaPlaylistParser().writePlaylistAsString(newPlayList);
if (parameterExists) {
newData = modifyManifestFileContent(newData, token, subscriberId, subscriberCode, SEGMENT_FILE_REGEX);
}

// Write the data into the output stream
response.setContentLength(newData.length());
response.getOutputStream().write(newData.getBytes());

// Commit the written data
response.getWriter().flush();


} catch (Exception e) {
response.setContentLength(responseWrapper.getContentSize());
response.getOutputStream().write(responseWrapper.getContentAsByteArray());
response.flushBuffer();

}
// Write final modified data to response
responseWrapper.resetBuffer(); // Clears any previous response data
responseWrapper.getOutputStream().write(newData.getBytes(StandardCharsets.UTF_8));
//copyBodyToResponse is called in finally block
}
//we don't need else block because we are calling copyBodyToResponse in finally block
}
}
}
else {
catch (Exception e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
finally
{
// Ensure the response body is copied back after all modifications
//IT IS CALLED FOR ALL CASES
responseWrapper.copyBodyToResponse();
}
}
else
{
chain.doFilter(httpRequest, response);
}

}

private void addSecurityParametersToSegmentUrls(String token, String subscriberId, String subscriberCode, ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {
private void addSecurityParametersToSegmentUrls(String token, String subscriberId, String subscriberCode, ServletRequest request, ContentCachingResponseWrapper response, FilterChain chain) throws IOException, ServletException {

addSecurityParametersToURLs(token, subscriberId, subscriberCode, request, response, chain, SEGMENT_FILE_REGEX);
}

public void addSecurityParametersToAdaptiveM3u8File(String token, String subscriberId, String subscriberCode, ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {
public void addSecurityParametersToAdaptiveM3u8File(String token, String subscriberId, String subscriberCode, ServletRequest request, ContentCachingResponseWrapper response, FilterChain chain) throws IOException, ServletException {
addSecurityParametersToURLs(token, subscriberId, subscriberCode, request, response, chain, MANIFEST_FILE_REGEX);
}

public void addSecurityParametersToURLs(String token, String subscriberId, String subscriberCode,
ServletRequest request, ServletResponse response, FilterChain chain,
String regex) throws IOException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(httpResponse);
ServletRequest request, ContentCachingResponseWrapper responseWrapper, FilterChain chain,
String regex) throws IOException, ServletException
{

try {
chain.doFilter(request, responseWrapper);
int status = responseWrapper.getStatus();
chain.doFilter(request, responseWrapper);
int status = responseWrapper.getStatus();

if (status >= HttpServletResponse.SC_OK && status <= HttpServletResponse.SC_BAD_REQUEST) {
byte[] originalData = responseWrapper.getContentAsByteArray();
String original = new String(originalData);
if (status >= HttpServletResponse.SC_OK && status <= HttpServletResponse.SC_BAD_REQUEST) {
byte[] originalData = responseWrapper.getContentAsByteArray();
String original = new String(originalData);

String modifiedContent = modifyManifestFileContent(original, token, subscriberId, subscriberCode, regex);
response.setContentLength(modifiedContent.length());
response.getOutputStream().write(modifiedContent.getBytes());
response.getOutputStream().flush();
}
} catch (Exception e) {
logger.error(ExceptionUtils.getStackTrace(e));
// In case of an error, revert to the original response content
byte[] originalContent = responseWrapper.getContentAsByteArray();
response.setContentLength(originalContent.length);
response.getOutputStream().write(originalContent);
response.flushBuffer();
String modifiedContent = modifyManifestFileContent(original, token, subscriberId, subscriberCode, regex);
responseWrapper.resetBuffer();
responseWrapper.getOutputStream().write(modifiedContent.getBytes());
//responseWrapper.copyBodyToResponse() is called in finaally block
}

}

private String modifyManifestFileContent(String original, String token, String subscriberId, String subscriberCode, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(original);

StringBuffer result = new StringBuffer();
StringBuilder result = new StringBuilder();
while (matcher.find()) {
String replacementString = matcher.group();

if (replacementString.contains("?")) {
replacementString += "&";
}
else {
replacementString += "?";
replacementString += "?";
}

if (!StringUtils.isNullOrEmpty(subscriberCode)) {
Expand All @@ -210,7 +209,6 @@ private String modifyManifestFileContent(String original, String token, String s
}
matcher.appendTail(result);

String modifiedContent = result.toString();
return modifiedContent;
return result.toString();
}
}
Loading

0 comments on commit d8abd5c

Please sign in to comment.