[PATCH][KERNEL] EB13 camera video lag & sports mode FC fix

Search This thread

mkasick

Retired Recognized Developer
Aug 10, 2009
470
830
Attached is a kernel source patch that fixes the EB13 camera video lag and "Sports" scene mode force-close. It's actually the same kernel bug that's responsible for both.

Also attached is an Odin/redbend-flashable, otherwise stock EB13 kernel with this patch applied. It's intended for anyone who wishes to further test the fix and who is familiar with Odin and/or redbend_ua. For others, I'd recommend waiting until one of the custom kernels integrates the patch or until Sprint releases an official update.

I'll update this post in the morning with a workup of the bug (done, see below), since it's a bit interesting/illustrative. And yes, it's very simple and very silly. One of those things that really never should've happened. Thanks to everyone in the solutions thread for providing clues that were instrumental in locating it.

Bug details:

Shortly after the release of EB13 folks reported lag when recording videos, particularly in low light. Although not obviously related at the time, folks also reported that switching to "Sports" scene mode results in a force-closed (and in my experience, renders the screen inoperable as well, sigh). Folks in the solutions thread also reported that (i) these problems are new to EB13, they weren't present in DK28; and (ii) replacing the user-space camera components (app, libraries, etc.) with DK28 versions did not resolve the problems, implying they were likely due to one or more kernel bugs.

Unfortunately we do not have the DK28 source code to compare EB13 against, but at least knowing that these problems weren't present in DK28 helps narrow down the possible bug locations quite dramatically. Furthermore, it's quite likely that this bug was introduced rather recently, as I imagine it would've been caught by internal testing had it been present in say, December.

So with that in mind, I sorted the kernel source files by modification time and started looking for the most recently-changed files that might be relevant to the camera driver. "include/linux/videodev2_samsung.h" was the first hit with a modification date of 2/8, and indeed it's used by the camera driver ("drivers/media/video/victory/ce147.c", itself last modified on 12/1). Again, we don't have DK28 sources for comparison, but fortunately header files typically don't change too significantly and a comparison (diff) against the DI18 version was rather easy to follow.

And yes, a snippet of code stood out right away as rather strange, especially given the cirumstances of the problem:
Code:
enum v4l2_iso_mode {
        ISO_AUTO = 0,
        ISO_50,
        ISO_100,
        ISO_200,
        ISO_400,
        ISO_800,
        ISO_1600,
        ISO_FIREWORKS, // Added since DI18.
        ISO_SPORTS,
        ISO_NIGHT,
        ISO_MOVIE,
        ISO_MAX,
};
For folks less-familiar with C, this code defines an enumerated type, basically a mapping of "descriptive labels" to numeric values; in this case: ISO_AUTO=0 ISO_50=1, ISO_100=2, etc. This enables kernel code to contain descriptive statements like "iso_mode = ISO_200;" instead of the more arbitrary "iso_mode = 3;".

Now, as the above comment (which I added, but the diff points it out) suggests, ISO_FIREWORKS is a new speed that was added to the middle of the enum since DI18. Seasoned C programmers will recognize that, this is often something that leads to trouble. To understand why, compare the "before" and "after" enum mappings:
Code:
Before:          After:

ISO_AUTO:   0    ISO_AUTO:       0   
ISO_50:     1    ISO_50:         1   
ISO_100:    2    ISO_100:        2   
ISO_200:    3    ISO_200:        3   
ISO_400:    4    ISO_400:        4   
ISO_800:    5    ISO_800:        5   
ISO_1600:   6    ISO_1600:       6
ISO_SPORTS: 7    ISO_FIREWORKS:  7
ISO_NIGHT:  8    ISO_SPORTS:     8
ISO_MOVIE:  9    ISO_NIGHT:      9
                 ISO_MOVIE:     10
The addition of ISO_FIREWORDS to the middle of the enum shifts the mapping of any labels below it, in this case ISO_SPORTS, ISO_NIGHT, and ISO_MOVIE. This isn't fatal, but it does mean that all code that uses the enum needs to be recompiled to reflect the new mapping. Often, kernel header files contain data types that are exclusive to the kernel, so any relevant code gets recompiled as part of the process of compiling a kernel.

But as it turns out, the entries in this enum are used in exactly one location (on the Epic anyways) in the kernel: as a case in a switch statement in the camera driver that sets the ISO mode in a camera hardware register. This means, assuming these values are used at all, they must be provided by a user-space library. In other words, the enum mapping is an integral part of the driver API, and not something that can be altered willy-nilly.

So basically, on EB13 when the Camera app goes to record a movie, it sets mode ISO_MOVIE (9), which the kernel interprets as ISO_NIGHT and sends to the camera hardware. Presumably ISO_NIGHT biases picture quality over shutter speed, hence the blurry laggy video when recording. Similarly, ISO_NIGHT => 8 => ISO_SPORTS (which no one noticed), and ISO_SPORTS => 7 => ISO_FIREWORKS. Except ISO_FIREWORKS isn't implemented, so the driver call fails which results in the force close. Oops!

The fix is fairly simple, just remove ISO_FIREWORKS from the enum. This allows the kernel and the user-space libraries to agree on the mapping. And since ISO_FIREWORKS isn't even implemented in the kernel, no harm can possibly come from it.

Finally, as I stated earlier, this is a bug that never should've happened, for two reasons. First, it was introduced into the Epic kernel source tree after DK28. Now, keep in mind that DK28 was effectively a Froyo "release candidate", especially given that it was packaged up as an OTA update and accidentally pushed to some handsets. Any changes made to the kernel post-DK28 should be limited to strict bug fixes only. The addition of ISO_FIREWORKS to the enum is not part of any bug fix (indeed it introduces one), rather one would consider it a "new feature". But "new features" shouldn't creep into stable code trees. This suggests poor code management.

Second, this alteration would've been a non-issue had ISO_FIREWORKS been appended to the end of the enum, just before ISO_MAX (which, presumably just reports the numer of entries in the enum as opposed to describing a particular mode). This would've assiged ISO_FIREWORKS to an unused value, instead of remapping existing values. Adding ISO_FIREWORKS to the middle of the enum is a particularly short-sighted choice, as it immediately renders any code that uses it unnecessarilly incompatible with new kernels. Adding ISO_FIREWORKS to the end preserves backwards compatibility, for free, with absolutely no downsides--why not do that instead?

So, in short, the failure to properly consider both of these issues, as well as the neglect to notice the change, bespeaks of an incompetent moment on the part of Samsung. If the change really was made on 2/8, one can't really blame Sprint for failing to pick it up during last-minute testing. I'm not sure how much this particular bug was a factor in Sprint pulling the EB13 update, but it's pretty embarassing that it made it out there in the first place.

Mirror links (does not require forum login):
epic_camera_fix-EB13.diff
epic_camera_fix-EB13.tar
epic_stock-EB13.tar (for flashing back to the stock EB13 kernel)
 

Attachments

  • epic_camera_fix-EB13.diff.txt
    303 bytes · Views: 183
  • epic_camera_fix-EB13.tar
    5.5 MB · Views: 200
  • epic_stock-EB13.tar
    5.5 MB · Views: 37
Last edited:

FoxRacR17

Senior Member
Oct 27, 2008
235
2
THANKS! leave it up to xda to do a better job then Samsung lol

Sent from my SPH-D700 using XDA App
 

tmspyder

Senior Member
Nov 12, 2010
165
13
Sweet,
tested working perfect. the LSD trails in video are gone and no FC in sports mode. TY so much.
 

MoCoTerp

Member
Aug 19, 2010
33
1
Noob question.

Do you put this in PDA? Also no need for PIT or modem file right?

Via TapaTalk on Nook Tablet

-Edit-

Okay, used Odin, put patch in PDA with nothing else set. Worked perfectly! Thanks to all!
 
Last edited:

muyoso

Senior Member
Oct 23, 2007
2,492
492
Can't wait to hear the details behind the bug.
Sent from my SPH-D700 using XDA App
 

Top Liked Posts

  • There are no posts matching your filters.
  • 47
    Attached is a kernel source patch that fixes the EB13 camera video lag and "Sports" scene mode force-close. It's actually the same kernel bug that's responsible for both.

    Also attached is an Odin/redbend-flashable, otherwise stock EB13 kernel with this patch applied. It's intended for anyone who wishes to further test the fix and who is familiar with Odin and/or redbend_ua. For others, I'd recommend waiting until one of the custom kernels integrates the patch or until Sprint releases an official update.

    I'll update this post in the morning with a workup of the bug (done, see below), since it's a bit interesting/illustrative. And yes, it's very simple and very silly. One of those things that really never should've happened. Thanks to everyone in the solutions thread for providing clues that were instrumental in locating it.

    Bug details:

    Shortly after the release of EB13 folks reported lag when recording videos, particularly in low light. Although not obviously related at the time, folks also reported that switching to "Sports" scene mode results in a force-closed (and in my experience, renders the screen inoperable as well, sigh). Folks in the solutions thread also reported that (i) these problems are new to EB13, they weren't present in DK28; and (ii) replacing the user-space camera components (app, libraries, etc.) with DK28 versions did not resolve the problems, implying they were likely due to one or more kernel bugs.

    Unfortunately we do not have the DK28 source code to compare EB13 against, but at least knowing that these problems weren't present in DK28 helps narrow down the possible bug locations quite dramatically. Furthermore, it's quite likely that this bug was introduced rather recently, as I imagine it would've been caught by internal testing had it been present in say, December.

    So with that in mind, I sorted the kernel source files by modification time and started looking for the most recently-changed files that might be relevant to the camera driver. "include/linux/videodev2_samsung.h" was the first hit with a modification date of 2/8, and indeed it's used by the camera driver ("drivers/media/video/victory/ce147.c", itself last modified on 12/1). Again, we don't have DK28 sources for comparison, but fortunately header files typically don't change too significantly and a comparison (diff) against the DI18 version was rather easy to follow.

    And yes, a snippet of code stood out right away as rather strange, especially given the cirumstances of the problem:
    Code:
    enum v4l2_iso_mode {
            ISO_AUTO = 0,
            ISO_50,
            ISO_100,
            ISO_200,
            ISO_400,
            ISO_800,
            ISO_1600,
            ISO_FIREWORKS, // Added since DI18.
            ISO_SPORTS,
            ISO_NIGHT,
            ISO_MOVIE,
            ISO_MAX,
    };
    For folks less-familiar with C, this code defines an enumerated type, basically a mapping of "descriptive labels" to numeric values; in this case: ISO_AUTO=0 ISO_50=1, ISO_100=2, etc. This enables kernel code to contain descriptive statements like "iso_mode = ISO_200;" instead of the more arbitrary "iso_mode = 3;".

    Now, as the above comment (which I added, but the diff points it out) suggests, ISO_FIREWORKS is a new speed that was added to the middle of the enum since DI18. Seasoned C programmers will recognize that, this is often something that leads to trouble. To understand why, compare the "before" and "after" enum mappings:
    Code:
    Before:          After:
    
    ISO_AUTO:   0    ISO_AUTO:       0   
    ISO_50:     1    ISO_50:         1   
    ISO_100:    2    ISO_100:        2   
    ISO_200:    3    ISO_200:        3   
    ISO_400:    4    ISO_400:        4   
    ISO_800:    5    ISO_800:        5   
    ISO_1600:   6    ISO_1600:       6
    ISO_SPORTS: 7    ISO_FIREWORKS:  7
    ISO_NIGHT:  8    ISO_SPORTS:     8
    ISO_MOVIE:  9    ISO_NIGHT:      9
                     ISO_MOVIE:     10
    The addition of ISO_FIREWORDS to the middle of the enum shifts the mapping of any labels below it, in this case ISO_SPORTS, ISO_NIGHT, and ISO_MOVIE. This isn't fatal, but it does mean that all code that uses the enum needs to be recompiled to reflect the new mapping. Often, kernel header files contain data types that are exclusive to the kernel, so any relevant code gets recompiled as part of the process of compiling a kernel.

    But as it turns out, the entries in this enum are used in exactly one location (on the Epic anyways) in the kernel: as a case in a switch statement in the camera driver that sets the ISO mode in a camera hardware register. This means, assuming these values are used at all, they must be provided by a user-space library. In other words, the enum mapping is an integral part of the driver API, and not something that can be altered willy-nilly.

    So basically, on EB13 when the Camera app goes to record a movie, it sets mode ISO_MOVIE (9), which the kernel interprets as ISO_NIGHT and sends to the camera hardware. Presumably ISO_NIGHT biases picture quality over shutter speed, hence the blurry laggy video when recording. Similarly, ISO_NIGHT => 8 => ISO_SPORTS (which no one noticed), and ISO_SPORTS => 7 => ISO_FIREWORKS. Except ISO_FIREWORKS isn't implemented, so the driver call fails which results in the force close. Oops!

    The fix is fairly simple, just remove ISO_FIREWORKS from the enum. This allows the kernel and the user-space libraries to agree on the mapping. And since ISO_FIREWORKS isn't even implemented in the kernel, no harm can possibly come from it.

    Finally, as I stated earlier, this is a bug that never should've happened, for two reasons. First, it was introduced into the Epic kernel source tree after DK28. Now, keep in mind that DK28 was effectively a Froyo "release candidate", especially given that it was packaged up as an OTA update and accidentally pushed to some handsets. Any changes made to the kernel post-DK28 should be limited to strict bug fixes only. The addition of ISO_FIREWORKS to the enum is not part of any bug fix (indeed it introduces one), rather one would consider it a "new feature". But "new features" shouldn't creep into stable code trees. This suggests poor code management.

    Second, this alteration would've been a non-issue had ISO_FIREWORKS been appended to the end of the enum, just before ISO_MAX (which, presumably just reports the numer of entries in the enum as opposed to describing a particular mode). This would've assiged ISO_FIREWORKS to an unused value, instead of remapping existing values. Adding ISO_FIREWORKS to the middle of the enum is a particularly short-sighted choice, as it immediately renders any code that uses it unnecessarilly incompatible with new kernels. Adding ISO_FIREWORKS to the end preserves backwards compatibility, for free, with absolutely no downsides--why not do that instead?

    So, in short, the failure to properly consider both of these issues, as well as the neglect to notice the change, bespeaks of an incompetent moment on the part of Samsung. If the change really was made on 2/8, one can't really blame Sprint for failing to pick it up during last-minute testing. I'm not sure how much this particular bug was a factor in Sprint pulling the EB13 update, but it's pretty embarassing that it made it out there in the first place.

    Mirror links (does not require forum login):
    epic_camera_fix-EB13.diff
    epic_camera_fix-EB13.tar
    epic_stock-EB13.tar (for flashing back to the stock EB13 kernel)
    3
    I'm sure the Genocide kernel is fine, but as I read it it's an overclocking kernel. I'd rather not set up overclocking
    I don't believe you have to enable overclocking in Genocide. It should run at the normal Epic clock speed if you do nothing more.

    I recommend folks who want this patch to use a custom kernel as I don't intend to support the test kernel I posted long-term. That said, it should be perfectly fine to use as a stock+fix stopgap until Sprint releases an official update, which hopefully should be shortly.

    Instructions for flashing a kernel with Odin are mid-way down the OP in the Return to Stock thread:
    If you only want to revert back to the stock kernel you can place just the kernel file (SPH-D700.zImage.stock.tar) in the PDA portion with the .pit and that will over write any kernel changes you have made leaving everything else in place.
    Replace SPH-D700.zImage.stock.tar with epic_camera_fix-EB13.tar of course.

    Also, I updated the OP with a detailed description of the bug. Hope it proves insightful for some folks.
    3
    Procedure to flash this kernel

    I'd like to apply this fix to my camera...can somebody please make a tutorial for noobs and explain step by step how apply it?

    thank you :)

    The following were well-presented steps by Wosdaman for upgrading to the EB13 update in the first post of this thread, but they are the same steps you will need to follow for flashing the patched kernel provided by mkasick in this thread. For simplicity, I am pasting the steps from Whosdaman's post below, replacing the EB13 firmware file name (in Whosdaman's post) with the file name of mkasick's fixed version of the kernel:

    1. Download Samsung_Mobile_Driver_V1.3.800_For_SPH-d700_Epic_4G.zip
    2. Unzip the file and install the driver
    3. Download Odin3+v1.61andepic.pit.zip
    4. Unzip the file and open up "Odin3+v1.61.exe"
    5. Put your phone into "Download Mode" by doing the following:
    - Pull out battery
    - Put in battery
    - Push and hold "1" on your keyboard
    - Power on device while holding "1"
    6. Plug your Epic 4G into the computer
    7. Download "epic_camera_fix-EB13.tar" provided in the first post in this thread
    8. Place the file in the "PDA" slot
    9. Start flashing

    I am going to use the same procedure outlined above to flash mkasick's fixed kernel. Based on my research, merely flashing a kernel should retain all data and settings on the phone. If someone disagrees with me on anything, please feel free to correct me.

    Update: I just flashed the kernel following the steps above, and everything looks fine. The stuttering/laggy behavior of the camcorder (not the camera) is gone, and it works fine on the Sports Scene mode for the camera (not the camcorder), too. All data is intact. Thank you so much, mkasick!
    1
    Thank you! This will be in the ACS kernel team's kernel.
    1
    I haven't had a chance to test this yet, but wouldn't a better solution be moving the ISO_FIREWORKS "enum" to the bottom, rather than simply removing it?
    No, it's a mapping that both the camera kernel driver and the camera application libraries have to agree upon. The bug is that the kernel mapping was changed without also being changed in the libraries. So the fix is to undo the change in the kernel driver, so they agree on the mapping again.

    Moving ISO_FIREWORKS to the end of the enum wouldn't be harmful, but it wouldn't be helpful either as the camera libraries would be unaware of that change as well.

    It's already been stated that there is in fact a fireworks mode (maybe it's not fully implemented yet?), so simply removing the "enum" could likely cause issues?
    It uses an existing ISO mode at present, not its own. If it did use its own ISO setting, then the Camera app would force close with the fix in place, which it doesn't. I don't know which mode it uses off hand, but if it were important enough I could add a debug statement to the kernel to find out.

    I am wondering if I am the only one who still sees the lag while moving camera over a target with low light. I don't experience any lag in the video recording mode, but in the camera mode, I still do.
    There is camera lag in low light, but that's intentional. The earlier threads go into detail as to why, but in short: in low-light there's a tradeoff between shutter speed and picture quality. So when taking a still photo, the camera biases towards slower shutter speed (which adds lag) and higher picture quality. When recording a video, it does the opposite.

    This lag does not hinder the functionality of the camera, but thought it would be just easy as correcting the lag in the video mode.
    If you really wanted this, the Camera app would have to be modified to set ISO_MOVIE while in "preview" mode, then set the desired ISO mode while taking a photo, and back to ISO_MOVIE when finished. I'm not sure such a change is necessarily desirable. But if it were, we would need the source code to the Camera app which I believe we don't have. But I haven't checked the platform stuff in too much detail.